User Tools

Site Tools


Sidebar

<menu col=1,align=center>

<item>Documentation||[[lara:documentation]]|{{:lara:img:dictionary.png?25}}</item>
<item>Downloads||[[lara:downloads]]| {{:lara:img:projects.png?25}}</item>
<item>Tutorials||[[lara:tutorial]]|{{:lara:img:books.png?25}}</item>
<item>Other uses of LARA||[[lara:other]]|{{:lara:img:globe.png?25}}</item>
<item>About Us||[[https://sites.google.com/site/specsfeup/]]| {{:lara:img:specslogo.png?25}}</item>
<item>Projects||[[lara:usage]]| {{:lara:img:math.png?25}}</item>

</menu>

/* They are empty */ /* <item>FAQ||faq|</item> */ /* <item>Dev. Team||team| </item> */ /* <item>About LARA||about|</item> */

lara:tutorial:languagespecification

Writing a Target Language Specification

;#; ← Advanced LARA | Language Specification | 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, appfile means that we can select files inside the app join point. Some important remarks of this example:

  1. The gray arrow between assignExprexpr means that assignExpr inherits everything that expr contains, including selectable join points, attributes and actions;
  2. The arrows between bodyloop defines that body is able to select the loops inside itself and, in turn, loop is able to select its own body;
  3. The two arrows connecting bodystmt 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.

<imgcaption jmpGraph|A simple example of a join point model hierarchy.> <graphviz dot center width=330> 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];

} </graphviz> </imgcaption>

The Join Point List Declaration

The join point model is specified in an xml format that starts with a <joinpoints> element that gather all the available join points.

<joinpoints>
	<!-- ... -->
</joinpoints>

Inside this element we specify all the join points available in the target language. Each join point is specified inside a <joinpoint> 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.

<joinpoints>
        <joinpoint name="application"/>
        <joinpoint name="file"/>
	<joinpoint name="function"/>
	<joinpoint name="body"/>
        <joinpoint name="loop"/>
        <joinpoint name="var"/>
        <joinpoint name="stmt"/>
        <joinpoint name="assignExpr" extends="expr"/>
        <joinpoint name="expr"/>
</joinpoints>

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.

<joinpoints root_class="application" root_alias="app">
        <joinpoint name="application"/>
        <joinpoint name="file"/>
	<joinpoint name="function"/>
	<joinpoint name="body"/>
        <joinpoint name="loop"/>
        <joinpoint name="var"/>
        <joinpoint name="stmt"/>
        <joinpoint name="assignExpr" extends="expr"/>
        <joinpoint name="expr"/>
</joinpoints>

Defining the Hierarchy

The previous example shows the complete list of join points available in <imgref jmpGraph> 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 <select> elements inside a join point element.

Each select element defines a join point that is selectable by the container. The element contains two attributes: class (mandatory) defines the joinpoint class of the selectable join point, and alias (optional) defines the alias used for this select. The last attribute is useful when we intend to use a different name for the select, instead of the class “name”, or when different join points share the same class, but they point to specific parts in the code. The last is the example of stmt and first_stmt, in <imgref jmpGraph>, where stmt refers to every statement present in a body and first_stmt only refers to the first statement of the body.

   <joinpoint name="body">
       <select class="stmt"/>
       <select class="stmt" alias="first_stmt"/>
   </joinpoint>

By using the select element we are able to fully define our join point hierarchy. The following code depicts the complete join point model hierarchy defined in the graph of <imgref jmpGraph>.

joinPointModel.xml
<joinpoints root_class="application" root_alias="app">
   <joinpoint name="application">
       <select class="file"/> 
   </joinpoint>
   <joinpoint name="file">
       <select class="function"/> 
   </joinpoint>
   <joinpoint name="function">
       <select class="body"/> 
   </joinpoint>
   <joinpoint name="body">
       <select class="var"/> 
       <select class="loop"/>
       <select class="assignExpr"/>
       <select class="stmt"/>
       <select class="stmt" alias="first_stmt"/>
   </joinpoint>
   <joinpoint name="loop">
       <select class="body"/>
   </joinpoint>
   <joinpoint name="var"/>
   <joinpoint name="stmt"/>
   <joinpoint name="assignExpr" extends="expr"/>
   <joinpoint name="expr"/>
</joinpoints>

Attributes Model

Once the join point model is defined, we have to describe the information one can retrieve from a join point, in other words, the attributes associated to the join point class. The attributes are defined in a xml formatted file separated from the join point model. For this part of the tutorial we assume the following (example) information can be retrieved from the join point model defined in <imgref jmpGraph>. Note that the global attributes are information that can be retrieved from ANY declared join point.

Join Point Attribute Type Description
Global Attributes uid int the unique identifier of the join point
src_code string source code representation for the join point
application name string the name of the application
folder string the directory of the target source code
num_src_files int the number of source files
file name string the name of the file
path string the path to the file
function name string the name of the function
return_type TypeDef the return type
body num_lines int number of lines of the body
num_reads int number of reads to a specific variable in this body
num_writes int number of writes to a specific variable in this body
var name string the name of the variable
type TypeDef the type of the variable
reference 'read', 'write' or 'decl' the type of reference to the variable
loop type 'for', 'while' or 'do-while' the type of the loop
rank string the rank of the loop inside its function
nested_level int the nesting level of the loop
expr type 'assign', 'binary', 'unary', 'access', 'call', 'id' or 'literal' the type of this expression
num_oper int number of operations in the expression
num_calls int number of function calls in the expression
num_array_refs int number of array references in the expression
assingExpr operator string the operator used in the assignment
stmt line int the line number of the statement

The list of attributes that a join point contains is defined as artifact. To start defining the list of artifacts we use the <artifacts> element, as defined below. This element does not contain any particular attribute to be defined.

<artifacts>
</artifacts>

Now each list of attributes, for each join point class, is defined in an <artifact> element, in which the attribute class defines the join point associated to the attributes. This element also considers an optional attribute named default, which defines the default attribute used as filter in a select statement (please see LARA Basic 101 tutorial for further details).

<artifacts>
   <artifact class="application" default="name">
      ...
   </artifact>
   <artifact class="file" default="name">
      ...
   </artifact>
   <artifact class="function" default="name">
      ...
   </artifact>
   <artifact class="body">
      ...
   </artifact>
   ...
</artifacts>

Having the artifacts defined for each joint point class type, now we can list each attribute with the element <attribute> that has two mandatory parameters: the name of the attribute and its type. The type of an attribute may be defined in different forms:

  1. primitive - use one of the primitive types (similar to Java™): short, int, float, double, boolean, string, Object;
  2. join point - a join point class defined in the Join Point Model;
  3. enumeration - a list of the possible values the attribute may have (defined between'{' and '}', and each value separated by a ',' (comma));
  4. defined object - use an “object type” that is defined in the <artifacts> element.

Depending on the interpreter used, if the type used does not fit in one of these possibilities, the interpreter will warn the user, or possibly suspend the execution. The following code contains some of the attributes associated to each join point class. Note the use of an enumeration in the reference attribute of the join point var.

<artifacts>
   <artifact class="application" default="name">
     <attribute name="name"   type="string"/>
     <attribute name="folder" type="string"/>
     <attribute name="num_src_files" type="int"/>
   </artifact>
   <artifact class="file" default="name">
     <attribute name="name" type="string"/>
     <attribute name="path" type="string"/>
   </artifact>
   <artifact class="function" default="name">
     <attribute name="name" type="string"/>
     <attribute name="return_type" type="TypeDef"/>
   </artifact>
   <artifact class="var" default="name">
     <attribute name="name" type="string"/>
     <attribute name="type" type="TypeDef"/>
     <attribute name="reference" type="{read,write,decl}"/>
   </artifact>
   <artifact class="body">
      ...
   </artifact>
   ...
</artifacts>

As you can see we are using a TypeDef as type for the return_type attribute in join point function. Since this type is not a primitive, or a join point definition, we have to declare this new type as an object definition with the <object> element. The object contains a parameter defining its name and a list of attributes that this object may contain.

<artifacts>
   ...
   <object name="TypeDef">
     <attribute name="name"   type="string"/>
     <attribute name="base_type" type="string"/>
     ...
   </object>
</artifacts>

Now if we look at the description of the attributes num_reads and num_writes in the join point body, it says that returns the number of reads/writes of a specific variable, which then should be given as an input to allow the calculation. For this end, an attribute may have a list of <parameter> defining which inputs are necessary to get that attribute. In these examples, we are going to need one parameter: the string with the name of the variable.

<artifacts>
   ...
   <artifact class="body">
     <attribute name="num_lines" type="int"/>
     <attribute name="num_reads" type="int">
        <parameter name="var" type="string"/>
     </attribute>
     <attribute name="num_writes" type="int">
        <parameter name="var" type="string"/>
     </attribute>
   </artifact>
   ...
</artifacts>

Now the only part missing is the attributes that are common for all classes of join points. This is accomplished by defining an artifact without the class specified, or by defining the class as “*”, i.e. ANY class.

<artifacts>
   <artifact class="*">
     <attribute name="uid"   type="int"/>
     <attribute name="src_code" type="string"/>
   </artifact>
   ...
</artifacts>

This last version of the attributes model contains all the attributes defined in the table above. Note that since we defined in the join point model that assignExpr extends the expr class, all the attributes from expr is also available in assignExpr.

artifacts.xml
<artifacts>
   <artifact class="*">
     <attribute name="uid"   type="int"/>
     <attribute name="src_code" type="string"/>
   </artifact>
 
   <artifact class="application" default="name">
     <attribute name="name"   type="string"/>
     <attribute name="folder" type="string"/>
     <attribute name="num_src_files" type="int"/>
   </artifact>
   <artifact class="file" default="name">
     <attribute name="name" type="string"/>
     <attribute name="path" type="string"/>
   </artifact>
   <artifact class="function" default="name">
     <attribute name="name" type="string"/>
     <attribute name="return_type" type="TypeDef"/>
   </artifact>
   <artifact class="body">
     <attribute name="num_lines" type="int"/>
     <attribute name="num_reads" type="int">
        <parameter name="var" type="string"/>
     </attribute>
     <attribute name="num_writes" type="int">
        <parameter name="var" type="string"/>
     </attribute>
   </artifact>
   <artifact class="var" default="name">
     <attribute name="name" type="string"/>
     <attribute name="type" type="TypeDef"/>
     <attribute name="reference" type="{read,write,decl}"/>
   </artifact>   
   <artifact class="loop" default="type">
     <attribute name="type" type="{for,while,do-while}"/>
     <attribute name="rank" type="string"/>
     <attribute name="nested_level" type="int"/>
   </artifact>
   <artifact class="expr" default="type">
     <attribute name="type" type="{assign,binary,unary,access,call,id,literal}"/>
     <attribute name="num_oper" type="int"/>
     <attribute name="num_calls" type="int"/>
     <attribute name="num_array_refs" type="int"/>
   </artifact>
   <artifact class="assingExpr">
     <attribute name="operator" type="string"/>
   </artifact>
   <artifact class="stmt">
     <attribute name="line" type="int"/>
   </artifact>
 
   <object name="TypeDef">
     <attribute name="name"   type="string"/>
     <attribute name="base_type" type="string"/>
     <!-- other attributes -->
   </object>
</artifacts>

Action Model

The Actions Model defines the actions that can be applied over the application. By default, LARA has already the insert and def actions predefined. All other actions the weaver is able to perform is defined in this action model. The following table considers some actions that current existing weavers can perform.

Action Parameters Target Join Point Description
Name Type Default
report - - - any create a report of a join point by using its attributes
dna - - - function, loop extract a program DNA representation from the join point
map to string - function map computations to the given (embedded) target system
id string “0”
mode string “default”
unroll factor int 0 loop unroll a loop with a given factor
interchange loop2 loop - loop interchange the current loop with another, nested, loop

The action model is defined in its own xml formatted file. The list of actions is defined inside an <actions> element, with no attributes specified for this element.

<actions>
  ...
</actions>

Each action is then defined in an <action> element with two attributes: the name of the action (mandatory) and the target class (optional). The target class specifies the join point classes that can perform that action. Many classes may be used in the class attribute, separated with a ',' (comma). When the class attribute is not defined (or defined as “*”), then it is considered that the action can be performed in any join point class.

<actions>
  <action name="report"/>
  <action name="dna" class="function,loop"/>
  <action name="map" class="function"/>
  <action name="unroll" class="loop"/>
  <action name="interchange" class="loop"/>  
</actions>

The report and dna actions are ready to be used, since they do not require parameters. For the rest of the actions, a list of parameters is required. The parameters are defined each in a <parameter> element, inside the <action> element, with three attributes: the name and type (both mandatory), and the default value (optional) to be used if the parameter is not assigned in an action call, in a LARA aspect. The following code shows the complete action model for the actions defined in the table above.

actionModel.xml
<actions>
  <action name="report"/>
  <action name="dna" class="function,loop"/>
  <action name="map" class="function">
    <parameter name="to" type="string"/>
    <parameter name="id" type="string" default="0"/>
    <parameter name="mode" type="string" default="default"/>
  </action>
  <action name="unroll">
    <parameter name="factor" type="int" default="0"/>
  </action>
  <action name="interchange" class="loop">
    <parameter name="loop2" type="loop"/>
  </action> 
</actions>

;#; ← Advanced LARA | Language Specification | Basic larai → ;#;

lara/tutorial/languagespecification.txt · Last modified: 2019/09/22 15:47 (external edit)