The implementation concern addresses the development of applications based on C. On the core level, mbeddr comes with an implementation of C in MPS (MPS is discussed below). There are a few minor differences to C99, and the preprocessor is not exposed to the user. On the default extensions layer, the implementation concern comes with C extensions for interfaces and components, state machines and physical units, among others. The user extensions layer is by definition empty; users can easily extend the C core as well as any of the default extensions. The implementation concern also ships with an extensible debugger that is able to debug on the level of the extensions, so the abstractions do not break down when debugging becomes necessary. In the future, mbeddr will also support importing existing header and implementation files, to support interoperability with legacy libraries or implementation code. At the foundation layer, the implementation concern relies on a C compiler, a C debugger and tools for importing existing C code into mbeddr. By default, mbeddr generate make files that call
gcc, the debugger relies on
gdbdebugger and the Eclipse CDT for analyzing and importing textual C code. However, all of these can be changed.
This concern adds static analyses to some of the default extensions provided by the implementation concern. The analysis itself is performed by different existing external tools. However, mbeddr integrates the tools tightly by (a) providing language abstractions to conveniently describe behavior that can be analyzed, (b) translating this description to the input of the analysis tool, (c) running the tool, and (d) lifting the output of the tool back to the original abstraction level, to make it easier to understand for the user. The integrated analyses are based on symbolic model checking, SMT solving and C-level model-checking.
The process concern includes cross-cutting facilities that are useful to integrate mbeddr into the development process. They are generic in the sense that they can be integrated with arbitrary other languages, such as all the default and user-defined C extensions. mbeddr supports requirements engineering, product-line variability and documentation.
The requirements engineering support provides a language for describing requirements. Each requirement has an ID, a short description, an optional longer prose, a priority and any number of additional attributes. Requirements can also be nested and express relationships to other requirements. Requirements traces can be attached to any program element expressed in any language, supporting ubiquitous traceability. The requirements facility also supports reverse-tracing, so users can find out which parts of implementation artifacts depend on any particular requirement. Importantly, the requirements tooling is extensible; arbitrary additional data, expressed in any language, can be added to a requirement. This way, support for use cases, collaborations and scenarios has been added in a modular way.
mbeddr's support for product-line engineering can be split into two parts. First, there is a formalism for defining feature models and configurations based on these feature models. This represents a purely conceptual description of variability, independent of any particular implementation. The second part maps the variability expressed in feature models to arbitrary implementation artifacts by using presence conditions. These are Boolean expressions over features that determine how the program element they are attached to depends on the features selected for a given variant. If the expression evaluates to false, the element they are attached to is removed during generation. As a consequence of MPS' projectional editor, the presence conditions can also be evaluated in the editor. This allows program variants to be viewed and edited. While presence conditions are static and work for any language, there is also C-specific support to evaluate variability at runtime.
Visualization provides a facility to render diagrams. The facility relies on PlantUML as the backend, which supports most of UML's diagrams. The diagrams are shown directly inside the mbeddr IDE; by clicking on a node in the diagram, the respective source node in the MPS editor is selected, supporting navigability between diagram and code. Any program element can contribute visualizations, making the facility generically usable.
The documentation aspect supports writing prose documents as part of an mbeddr project, exportable as HTML or LaTeX. What makes this aspect worthwhile is that it supports close integration with program elements: program elements can be referenced (with real references that are renamed if the element itself is renamed) and program code can be embedded as text or as an image. The embedded code is updated whenever the document is regenerated, avoiding manual synchronization of the documentation. In the same way visualizations (as described in the previous paragraph) can be embedded, also updated whenever the document is re-rendered to LaTeX or HTML.
mbeddr relies on the JetBrains MPS language workbench. The JetBrains Meta Programming System is a projectional language workbench available as open source software under the Apache 2.0 license. The term Language Workbench was coined by Martin Fowler. He defines a language workbench as a tool with the following characteristics, all of which MPS exhibits: (1) Users can freely define languages which are fully integrated with each other. (2) The primary source of information is a persistent abstract representation. (3) A DSL is defined in three main parts: schema, editor(s), and generator(s). (4) Language users manipulate a DSL through a projectional editor. (5) A language workbench can persist incomplete or contradictory information.
One of the most important statement in this definition is languages which are fully integrated with each other. It is not enough for a language workbench to address the definition of a single language. It must be possible to define sets of languages, and, while each of them should be a well-defined module, it is also essential to be able to define how these languages integrate. MPS is particularly good at this.
MPS' Projectional editing does not rely on parsers. As a user edits a program, the AST is modified directly. A projection engine then creates some representation of the AST with which the user interacts, and which reflects the resulting changes. This approach is well-known from graphical editors: when editing a UML diagram, users do not draw pixels onto a canvas, and a "pixel parser" then creates the AST. Rather, the editor creates an instance of
uml.Classas a user drags a class from the palette onto the canvas. A projection engine renders the diagram by drawing a rectangle for the class. Programs are stored using a generic tree persistence format (such as XML). This approach can be generalized to work with any notation, including textual.
What makes projectional editing interesting for language workbenches in general, and for mbeddr in particular, are the following two characteristics. First, the approach can deal with arbitrary syntactic forms including textual, symbolic/mathematical, tabular and graphical. This means that much richer notations can be used in an integrated fashion, improving the usability to the end user. An example from mbeddr is the decision table shown in the picture above. Traditionally the tools for building textual and tabular/symbolic/graphical editors were very different in terms of their architecture and user experience, and integrating them seamlessly was a lot of work, and sometimes impossible. Second, if independently developed languages are composed, the resulting composite program is never syntactically ambiguous.