The compiler consists of three parts that will be presented in more details in the following sections:
A typical compilation consists of the following steps:
This part is responsible for reading user input (ie. BIP source code & command line argument) and transforming it into an intermediate representation that will be used throughout the other parts of the compiler. The current front-end contains a parser for the BIP language and a BIP meta-model that describes the intermediate representation. An instance of a BIP model represented in the BIP meta-model is called a BIP-EMF model (because it is a BIP model expressed using the Eclipse Modeling Framework (EMF) technology) in the following text. For more details on the internals, see Front-end.
The BIP language only deals with types. There is no support for running entities, even if the final result should be a running system. This missing information is usually filled by specifying a root component at compile time. The compiler (ie. the front-end) is then able to build both a type model (ie. a representation of the BIP source code given as input) and an instance model that represents the system you want to run. The distinction between the two can be subtle, especially when the concept of declaration is mixed in between:
These notions are similar to class/instance/object declaration that can be found in object oriented language. For example, in Java:
a component type = a class:
public class MyClass { ... }
a component (instance of a component type) = an object (instance of a class):
new MyClass();
a component declaration = an object declaration:
MyClass m;
Beware that a component declaration can trigger the creation of more than one instance. A component declaration usually is not a discriminant component identifier within the whole system.
The middle-end hosts all the BIP to BIP transformations. It acts on the BIP-EMF model by means of operations (but are not limited to):
The compiler currently does not have any such operation: the middle-end is empty. See Middle-end for more details.
The back-end gets the BIP-EMF model and is only allowed to read it and produce something, most probably some source code in another language (eg. C, C++, Aseba, ...) or even in BIP. Currently, the main back-end used is the C++ back-end that produces C++ code suitable for standard engine (see Installing & using available engines for the definition of a standard engine).
Several back-ends can be used at once; for example, you may need to get a BIP version of your input after some optimizations have been applied along with its corresponding C++ version. Compiler design forbids back-ends to interact (when there are several back-ends to execute, the compiler does not specify in which order they will be run or if the executions will be in parallel or not).
An engine takes some representation of a BIP model and computes corresponding execution sequences according to the BIP semantics. Usually, the representation used is a C++ software that is linked against the engine’s runtime to create an executable software. Typically, engines target one or more of the following main goals:
Typically, a back-end generates source code from a BIP model. This source code is then associated with a runtime, called an engine, that is responsible for the correct execution of the BIP model with respect to the BIP semantics.
The generated source code could be seen as yet another representation of the BIP model (with nothing added to the information contained in the BIP source code) suitable for a given engine (that implements the semantics of the language).