ReCooPLa Reconfiguration of Coordination Patterns Language

ReCooPLa was designed to describe the coordination-based reconfigurations referred by Oliveira and Barbosa (cf, publications of 2013). The main concept of this language is that of a reconfiguration.

ReCooPLa is comparable to other programming languages. We assume reconfiguration to be a first call concept in the language, as much as the function concept is in other programming languages. In fact, they share characteristics: both have a signature (identifier and arguments) and a body which assigns a specific behaviour. But in particular, a reconfiguration is always applied to, and always returns a, coordination pattern.

Reconfigurations accept arguments of the following data types: Name, Node, XOR, Set, Pair, Triple, Pattern and Channel, each one with its specificities. The reconfiguration body is a list of different sorts of instructions. We devote special attention to the instruction of applying (primitive, or previously defined) reconfigurations, since this operation is the only responsible for changing the internals of a coordination pattern.

To support the application of reconfigurations, the language counts on other constructs that mainly manipulate the parameters of each reconfiguration. In concrete, it provides means to declare and assign local variables. Field selectors, specific operations for structured data types and common Set operations (union, intersection and subtraction). Moreover, a control structure is provided to iterate over the elements of a Set.


In brief, ReCooPLa is a small language borrowing most of its constructs from imperative programming languages. Actually, reconfigurations are better expressed in a procedural/al- gorithmic way, which justifies the choice of an imperative style.

The complete grammar of ReCooPLa is presented below:

recoopla              : import* content
import                : 'import STRING ';'
content               : reconfiguration* main?

reconfiguration       : 'reconfiguration' ID '(' args? ')' '{' instruction+ '}' 
args                  : arg (';' arg)*
arg                   : datatype list_ids
datatype              : 'Pattern' | 'Channel' | 'Name' | 'Node' | 'Xor' | other_type '<' subtype '>'
other_type            : 'Set' | 'Pair' | 'Triple' 
subtype               : datatype 
list_ids              : ID (',' ID)*

instruction           : declaration ';' | assignment ';' | reconfiguration_apply ';' | for_instruction
declaration           : datatype var (',' var)*  
var                   : ID | assignment
assignment            : ID '@' assignment_member 
assignment_member     : expression | reconfiguration_apply    
reconfiguration_apply : ID? '@' reconfiguration_call 
reconfiguration_call  : ('join' | 'split' | 'par' | 'remove' | 'const' | 'id' | ID) operation_args
operation_args        : '(' op_args? ')' 
op_args               : expression (',' expression)*
for_instruction       : 'forall' '(' datatype ID ':' ID ')' '{' instruction+ '}' 

expression            : factor (expr_op factor)? 
expr_op               : '+' | '-' | '&'
factor                : ID '<' ID '>' | ID | operation | constructor
operation             : ID ('#' ID)? '.' attribute_call 
attribute_call        : 'in' ('[' INT ']')? | 'out' ('[' INT ']')? | 'name' | 'node' | 'names' | 'fst' | 'snd' | 'trd' | ID
constructor           : triple_cons | pair_cons | set_cons
triple_cons           : 'T' '(' expression ',' expression ',' expression ')'
pair_cons             : 'P' '(' expression ',' expression ')'
set_cons              : 'S' '(' expression (',' expression)* )? ')'
    

main                  : 'main' '(' main_args? ')' '{' main_instruction+ '}' 
main_args             : main_arg (';' main_arg)*
main_arg              : ID ids
ids                   : ID (',' ID)* 
main_instruction      : main_assignment ';'
                      | reconf_apply ';'
main_assignment       : ID ids '=' ID '@' reconfiguration_call
reconf_apply          : ID '@' reconfiguration_call

Reconfigurations

Formally, a sentence of ReCooPLa specifies one or more reconfigurations.



reconfiguration example (Set<Node> nodes)
{ 
    ...
}     

A reconfiguration is expressed by: the reserved word reconfiguration; an identifier representing the name of the reconfiguration that matches the usual regular expression for this kind of terminals; a list of arguments, which may be empty; and a reconfiguration body, which is a list of instructions as explained later in this section. In particular, each argument is aggregated by data type (i.e., data types are factored), unlike conventional languages, where data types are replicated for every different argument.



Data types

ReCooPLa builds on a small set of data types: primitives (Name, Node and Xor), generics (Set, Pair and Triple) and structured (Pattern and Channel).

Name is a string and represents a channel identifier or a channel end. Node, although considered a primitive data type, is internally seen as a set of names, to maintain compatibility with its definition. XOR is a particular case of Node, which has at least one input end and two (mutual exclusive) output ends. The generic data types are based on the Java generics, therefore it is necessary to give a type to their contents.

The structured data types have the following internal representation:

Channel
in: Set<Node>
out: Set<Node>
name: Name
Pattern
in: Set<Node>
out: Set<Node>
nodes: Set<Node>
names: Set<Name>

This notation follows the traditional approach of UML class diagrams, i.e. the top part contains the name of the structured data type, the middle part contains its attributes and the bottom part mentions its operations. Each instance of these types is endowed with attributes and operations, which can be accessed using selectors.



Reconfiguration Body

The reconfiguration body is a list of instructions inclosed between curly brackets. An instruction can be a declaration, an assignment, an iterative control structure, or an application of a reconfiguration.

A declaration is expressed as usual: a data type followed by an identifier or an assignment. In its turn, an assignment associates an expression, or an application of a reconfiguration, to an identifier.

The control structure marked by the reserved word forall, is used to iterate over a set of elements. Adopting a notation similar to Java, it requires a variable (of data type Set) to iterate over, and the declaration of a local variable that in each iteration assumes the value of each element in the provided set. Clearly, the data type of this variable shall be compatible with the data type of the elements inside the set. Again, a list of instructions defines the behaviour of this control structure.

The application of a reconfiguration, (c.f., reconfiguration_apply production in the grammar), is expressed by an identifier (to which a reconfiguration is applied) followed by @ operator and a reconfiguration name. The latter may be a primitive reconfiguration or another reconfiguration previously declared.

The @ operator stands for application. A reconfiguration is applied to a variable of type Pattern. In particular, we can omit the variable (optional identifier in the reconfiguration_apply production) when we want to refer to the pattern to which the reconfiguration being defined is applied.



Operations

An expression is composed of one or more operations. These can be specific constructors for generic data types, including nodes, or operations over generic and structured data types (c.f., constructors productions -- set_cons, pair_cons and triple_cons -- in the grammar).

Each constructor is defined as a reserved word (S stands for Set, P for Pair and T for Triple; and a list of values that shall agree to the data type.

For the Set data type, ReCooPLa provides the usual binary set operators: + for union, - for subtraction and & for intersection. For the remaining data types (except Node, XOR and Name), selectors are used to apply the operation. Symbol # is used to access a specific channel from the internal structure of a pattern.

An attribute_call correspond to an attribute or an operation associated to the last identifier, which must correspond to a variable of type Channel, Pattern, Pair or Triple. They are described below.

  • in: returns the input ports from the Pattern and Channel variables. It is possible to obtain a specific port refered by an optional integer parameter indexing a specific entry from the set (seen as a 0-indexed array).
  • out: returns the output ports from the Pattern and Channel variables. The optional parameter can be used as explained for the in attribute call.
  • name: returns the name of a Channel variable, also known as channel identifier.
  • nodes: returns all input and output ports plus all the internal nodes of a Pattern variable.
  • names: returns all channel identifiers associated to a Pattern variable.
  • fst, snd, trd: act, respectively, as the first, second and third projection from a tuple (Pair and Triple variables).



Example

reconfiguration removeP (Set<Name> Cs ){ 
    forall ( Name n : Cs){
        @ remove(n); 
    }
}

reconfiguration overlapP(Pattern p; Set<Pair<Node>> X){
    @ par (p);
    forall(Pair<Node>  n : X){
        Node n1, n2; 
        n1 = n.fst; 
        n2 = n.snd;
        Set E = S(n1, n2);
        @ join(E); 
    }
} 

In this example, two reconfigurations are declared: removeP and overlapP.

The former removes from a coordination pattern an entire set of channels by applying the remove primitive repeatedly.

The latter sets a coordination pattern in parallel with the original one, using the par primitive, and performs connections between the two patterns by applying the join primitive with suitable arguments.


These reconfiguration patterns are the implementation of the informal definitions presented by Oliveira and Barbosa (cf., publications of 2013).

Main

ReCooPLa allows for the specification of the actual application of reconfigurations to coordination patterns. This is expressed in a special reconfiguration marked with the reserved word main.

The main reconfiguration accepts a (possibly empty) list of arguments aggregated by data type, as in a normal reconfiguration. The difference is that in the main reconfiguration, data types are only references to available coordination patterns expressed in imported CooPLa files. The arguments are assumed as new instances of the given patterns that are to be reconfigured. These instances are defined with default stochastic information; and can not match an existing identifier of a stochastic instance declared in the imported CooPLa files. An exception is the Empty pattern, which is a structureless pattern whose instance(s) can be used in the body of the main to construct new patterns from nothing.



Body

The body of the main reconfiguration is a list of specific instructions, where an instruction is either an assignment or an isolated application of a reconfiguration (cf., main_instruction, main_assignment and reconf_apply productions in the grammar).

An assignment in the main is a declaration, expressed as usually, with a data type and a variable identifier, followed by a concrete application of a reconfiguration to the coordination pattern instances (which are either passed as arguments, imported, or freshly declared).

The data type corresponds to a coordination pattern name, which may or may not exist in the imported ones. If the pattern name does not exist, it becomes a new coordination pattern and the variable identifier is added as its instance; otherwise the structure assigned to the new instances is verified to ensure that it matches the expected coordination pattern. If the structures are similar, then the identifiers are added as instances of the pattern; otherwise they become instances of the multi-purpose pattern Reconfigured.

An isolated application of a reconfiguration, directly changes the target instance of coordination patter and associates it to the generic type Reconfigured, and remove it from its original pattern. The @ symbol is again used to express the application of reconfigurations. The arguments of a reconfiguration are obtained from the arguments of the main and freshly declared pattern instances, using the operations explained above to access nodes, channels and alike.



Example

import patterns.cpla;
import reconfigs.rcpla; 

main [Sequencer seq] {
seq @ removeP(S(seq#s1.name)); } 

A simple example of a main reconfiguration is presented aside. Therein, a Sequencer coordination pattern is reshaped through the application of the removeP reconfiguration (presented in the reconfiguration example.).


Notice both the import of the files where patterns and reconfigurations were previously defined.