ReFlO aims to provide a machine-assisted framework to support Design by Transformation, allowing domain-experts to encode domain knowledge about how programs are built in a particular domain, and developers to synthesize efficient program architectures, using the knowledge provided by domain-experts.
It provides a GEF graphical editor, which allows users to specify models using a pipe-and-filter (or dataflow) notation. Transformations, implemented using Epsilon, allow the users to create architectures, and incrementally refine and optimize them for specific platforms.
Users can also provide interpretations of architectures, in order to automatically compute properties about the architectures (e.g., performance costs), at different stages of development.
ReFlO also allows users to attach documentation info to their models, and later export the models to HTML (similarly to Javadoc).
To see ReFlO in action, watch the following screencasts!
ReFlO (v3.0.0) [~1.2 MB; for Eclipse 4.3]
ReFlO (v2.2.0) [~1.2 MB; for Eclipse 3.6]
Eclipse (v4.3.2) + ReFlO (v3.0.0) [~355 MB; for Windows]
Dependencies: the following Eclipse plugins need to be installed (click on the link to see how to install the plugins):
Installation steps:
dropins
and xform
).dropins
to Eclipse's
dropins
folder.
reflo
.xform
to reflo
project.xform.epf
from folder xform
.Not working? Download the full Eclipse installation, which already contains everything you need to use ReFlO.
A ReFlO Domain Model (RDM) encodes domain knowledge, i.e., interfaces of the domain and their implementations. To create a domain model, the user must create a diagram file, selecting File > New > Example... > Domainmodel Diagram, and then choose the name for the file.
After creating (and opening) the file, in the Pallete on the right, the user has available a list of objects and links he can use to build his models.
The user starts by creating layers, and then he adds the different model elements that encode the domain operations, implementations and optimizations, effectively defining a set of rewrite rules, which will be available when synthesizing program architectures. It is recommended to model the interfaces first, and then the algorithms/patterns, as the user may automatically add any of the defined interfaces to an algorithm/pattern, by selecting the algorithm/pattern box, right clicking, and selecting Wizards > Insert Interface (otherwise the user will have to manually add the interfaces, their ports, and set their attributes). The user will only have to set the values of the additional parameters of an interface (in case they exist) inside algorithms/patterns.
The name of the objects (layers, boxes, ports) is specified in the attribute
Name
.
The names must match the regular expression [a-zA-Z][a-zA-Z0-9_]*
.
Ports have the attribute Data Type
to store its data type (optional).
The additional parameters are specified in the boxes' attribute Parameters
,
using the notation name1 : type1, name2 : type2, ...
, or
name1 = value1, name2 = value2, ...
when the parameters' value
also needs to be provided (this happens for boxes that appear inside algorithms).
The parameters' types are optional.
ReFlO provides model validation, available in the menu Edit > Validate.
You can find a video here showing the creation of a RDM for the databases domain.
The different objects of RDM (boxes, ports, layers) have an attribute
(doc
) that should be used to put a description of the object.
The user can select a RDM diagram file, right click, and select ReFlO > Export as
HTML, to generate an HTML page that documents the RDM.
This HTML page will list the contents of the RDM, showing their figures, and their
descriptions.
ReFlO provides a mechanism to easily define several rewrite rules that have a common
shape, reducing the modeling effort.
Every rewrite rule can be used as a template.
This is done setting the Template
attribute of the interface being defined in
the rewrite rule.
The attribute should be null
, in case the rewrite rule is not used as a
template, or contain a string of format
(template_box1, template_box2, ...) := (real_box1, real_box2, ...) |
(real_box1', real_box2', ...)
, meaning that template_box1
,
template_box2
, ...
are parameterizable boxes, that can be
instantiated with real_box1
, real_box2
, ...
, or with
real_box1'
, real_box2'
, ...
.
That is, this attribute Template
defines the valid instantiations for the
template.
The users can define as many instantiations as they need for a templatized rewrite rule.
Architectures allow the user to specify programs and transform them. To create an architecture, the user must create a new diagram file, by selecting File > New > Example... > Architecture Diagram, and then choose the name for the file.
After creating an architecture diagram file, the first thing to do is to associate a RDM to it. To do this, the user must select the architecture diagram file and a RDM diagram file, right click, and select ReFlO > Sync ReFlO Domain Model. If the user decides to update the RDM, he must repeat this process (he may also need to close and reopen the file, for the changes to take effect).
Then the user can open the architecture diagram file, and in the Pallete on the right he will see the list of objects and links he can use to build his architectures.
These allow the user to specify an initial architecture, to later transform. The interfaces used to specify the initial architecture must be present in the RDM associated with this architecture diagram file. The interface may be created manually (creating the interfaces, the ports, and setting its attributes), or the user may select the architecture box, right click, and select Wizards > Insert Interface, which will insert the interface, according to its definition in the RDM (and the user will only have to set the values of the additional parameters of the box, in case they exist).
Given an architecture, users may apply transformations to it in order to derive architectures with desired properties (such as availability or efficiency). To apply a transformation, users should select the model elements to transform, and then right click, and select Wizards and the desired transformation.
The following transformations are available:
You can find a video here showing the derivation of an architecture.
Interpretations allow users to associate behavior with boxes, and execute architectures. This behavior can specify the computation the box represents, in which case executing the architecture would result in an interpretor, but may also capture other properties of the boxes. A typical example is to use interpretations to estimate performance costs for architectures.
An interpretation for a box is a function that compute properties about its outputs (or about the box itself) based on properties about its inputs (or about the box). Given an architecture, ReFlO can execute it, running these functions according to the topological order of boxes. Ports connected share properties, which means that when executing the architecture, the properties are propagated as usual when running a dataflow architecture. We noticed that some properties are easier to compute when inverting the order of execution of boxes, thus we provide backward interpretations.
Interpretations may be composed, that is, several interpretations may be executed in sequence, and an interpretation has access to properties set by previous interpretations. This allow users to specify interpretations in a modular way, and reuse an interpretation in different scenarios.
Interpretations are specified in Java, extending class
AbstractInterpretation
(this class is provided by jar file
Architecture.exec_*.jar
, which is installed in your Eclipse with ReFlO).
An interpretation is defined creating a Java package (the name of the package is the name of
the interpretation), and for each box existing in the domain models, a Java class shall be
created (with the name of the box).
The behavior is defined implementing method compute
.
The class provides methods to get and set the properties of the box and its ports, when
defining the compute
method.
Properties may be objects of any type, and are associated with a key of type
String
.
In the RDM, there is an attribute (Tf Path
) where the user should specify
the base path of the classes, and a package that is the root of the packages specifying the
different interpretations (Tf Package
).
These attributes are essential to allow ReFlO to locate the classes specifying the
interpretations.
In architectures, the users may also define interpretations for architectures' boxes, and define the properties of inputs of the architecture (or properties of outputs, for backward interpretations), which will be propagated through the architecture when executing interpretations.
Architectures' interpretations are defined similarly to interpretations for other boxes.
The specification of the architectures' inputs properties is done using a Java class that
extends class AbstractInit
, and defining method init
.
This class must be part of a package with the name of the interpretation that needs the
property being initialized.
Methods to set the properties are provided by class AbstractInit
.
As for RDM, architectures also have attributes Tf Path
and
Tf Package
to specify where classes are located.
Interpretations can be executed by selecting an architecture, right clicking, and
selecting Wizards > Run Interpretations.
Then, the user must introduce a comma separated list of interpretations to run.
The character ~
is used before the name of an interpretation to specify that
it is a backward interpretation.
Interpretations may also be used to define conditions that must be met in order to a box produce the desired behavior. This allows the user to validate architectures. More than that, this is useful to define implementations for interfaces that are only valid for specific inputs.
For example, a SORT
operation (that sorts a stream) may be implemented by an
algorithm that just outputs its inputs (i.e., an Identity
function), provided
that the input stream is already sorted.
If we define the Identity
as an implementation of SORT
, we
need to disallow the refinement of SORT
with the Identity
whenever
we do not know whether the stream is sorted.
This is accomplished defining an interpretation that computes a property (say
IsSorted
), which specifies how each operation affects the order of a stream.
This will be a postcondition of the boxes (operations).
Additionally, an interpretation must be defined to check if property
IsSorted
is defined whenever we try to refine SORT
with
Identity
.
Class AbstractInterpretation
also provides method addError
, which
must be called by the interpretation whenever a precondition is not met (to tell ReFlO
that a transformation is not valid in the current context, and thus it must be
disallowed).