Domain-specific Languages, Projectional Editor and MPS
Here you can find answers to the most frequent questions regarding MPS.
What are Domain-specific languages (DSLs)? How are they different from "real" programming languages?
A DSL is a language optimized for a specific problem domain. It is usually less complex than a general-purpose language, such as Java, C, or Ruby. DSLs are typically developed in close coordination with the experts in the domain, or field, for which the DSL is being designed.
In many cases, a DSL is intended to be used by non-programmers who are fluent in the domain the DSL targets. This means the language's notation and tool support should be optimized for non-programmers, so they only see elements and language aspects that are relevant to their domain, also known as Subject Matter Expert (SME).
What are the benefits of using a DSL compared with a regular programming language?
The benefits of using DSLs are numerous.
The end-user of the DSL becomes more efficient at working with their domain, because the level of abstraction is higher and they have to understand only the domain-specific part of the system – not the whole system.
If you are generating source code from your DSL program (as opposed to having it interpreted), you can use nice domain-specific abstractions without paying any runtime overhead. This is because the generator, just like a compiler, can remove the abstractions and generate efficient code.
A DSL allows you to separate essential elements of the domain from the complexity of the code. This improves the communication between the domain experts and the programmers.
Using DSLs and an execution engine makes the application logic expressed in the DSL code independent of the target platform.
Using DSLs can improve code quality, including having fewer bugs, better architectural conformance, and easy-to-maintain code. This is the result of limiting the user to modifying only certain components of the code, as well as the avoidance of duplication in code and the automation of repetitive work. In contrast to libraries and frameworks, DSLs can come with tooling support. Code completion, visualizations, debuggers, simulators and other niceties can be provided to improve the user experience.
How do DSLs and regular code fit together?
There are two fundamentally different ways of how traditional code and DSL code can be integrated, which are known as Internal and External DSLs. MPS supports both approaches.
The external way keeps DSL code and regular code in separate files. The DSL code is then transformed into programming language code by a code generator, or alternatively the program loads the domain-specific code and executes it. Think of SQL as an example of an external DSL.
The internal approach mixes both types of code in the same program file, leading to much tighter integration between DSL code and programming language code. The DSL reuses the grammar and the parser of the GPL (general-purpose language) and exploits the available extension options of the host language. It is worth mentioning that some GPLs are more suitable for extension than others.
What is Language-Oriented Programming?
The term language-oriented programming was coined by Sergey Dmitriev, the CEO of JetBrains and the founding father of MPS, in his 2004 article Language Oriented Programming: The Next Programming Paradigm. Other related approaches include Charles Simonyi’s Intentional Programming, and Martin Fowler’s approach described in his 2005 article Language Workbenches: The Killer-App for Domain Specific Languages?
The core idea is that we don't always use the same language when developing software, but choose one that fits each specific task best. In contrast to polyglot programming, which on the surface advocates a similar approach, language-oriented programming explicitly encourages developers to build their own DSLs, or to extend existing languages with domain-specific concepts as part of the approach. Developing a new language should become an integral part of software development. To make this feasible, language workbenches such as MPS are an important ingredient of the language-oriented approach.
Why extend a language? Aren't libraries good enough?
There are a couple of differences between a library and a language extension.
A language extension can come with its own syntax. With MPS's projectional editor, this syntax can be arbitrary and is not at all limited by the syntax of the extended language.
A language extension comes with its own constraints and type system, so your IDE can report errors statically.
Language extensions made with MPS are fully integrated into the IDE, so you get code completion, syntax highlighting, and refactoring support for your new language constructs.
A language extension is executed by compile-time transformation and translated into the target programming language code, so there is no runtime overhead that reflection or stacks of indirections would impose. This may be of particular importance when targeting resource-constrained systems.
What is Projectional Editing?
In parser-based approaches, users use text editors to enter character sequences that represent programs. A parser then checks the program for syntactic correctness and constructs an abstract syntax tree (AST) from the character sequence. The AST contains all the semantic information expressed by the program, meaning that keywords and purely syntactic aspects are omitted.
In projectional editors, the process happens the other way round: as a user edits the program, the AST is modified directly. This is similar to the MVC pattern where every editing action triggers a change in the AST. A projection engine then creates some representation of the AST for the user to interact with. This approach is well-known from various graphical editors. When editing a UML diagram, for example, users don't draw pixels onto a canvas for an "image parser" to read the drawing, parse it, and then create the AST. That would be way too limiting on what you could draw so that the engine would understand. Rather, the editor creates an instance of Class as you drag a class from the palette to the canvas. A projection engine renders the diagram, in this case drawing a rectangle for the class. You can then rearrange visual elements on the screen without changing the meaning of your diagram.
This approach can be generalized to also work with text editors. Every program element is stored as a node with a unique ID (UID) in the AST. References are based on actual pointers (references to UIDs). The AST is actually an Abstract Syntax Graph (AGT) because cross-references are first-class rather than being resolved after parsing. The program is then persisted to disk as XML, but this process is transparent to the user.
Why use Projectional Editing? Aren't text editors good enough?
Since no parsing is used in projectional editors, notations other than text can be used in the editor, such as graphs, math notations, diagrams, and forms. Since these non-textual notations are handled the same way as the textual ones, they can be mixed easily: tables can be embedded into a textual source, and textual languages can be used within table cells. Textual notations can also be used inside boxes or as connection labels in diagrams.
If different languages are combined, the resulting language may become ambiguous in parser-based systems since most grammar formalisms are not closed under composition. In projectional systems, this cannot happen. Any combination of languages will be syntactically valid (though semantics is a different issue).
What are the key benefits of using projectional editors instead of parsed languages?
A projectional editor gives the Abstract Syntax Tree (AST) a prominent role in code manipulation. Code is persisted, versioned, refactored, and edited in the AST form, which eliminates the need for repetitive text-to-model-and-back transformations. AST is a much richer representation of code, which avoids ambiguities. The AST can be projected on the screen for editing in any way the language designer desires. With projectional editors, your languages can:
Allow for non-parseable notations – so that tables, images, and GUI components may become part of the language syntax. The AST can easily accommodate for such language elements, and the projectional editor can draw any graphical shapes on the screen if needed.
Combine multiple languages, potentially developed by different vendors, in a single piece of code. Ambiguities that parsers might not be able to resolve are not an issue for projectional editors.
Handle context-sensitive and positional grammars.
Provide form-like notations – when targeting non-professional developers and domain experts, the preference is usually to use languages that offer a strict notation with a clear indication of the "moving" parts where the user is supposed to provide a value.
Offer multiple notations for a single language – users can view and edit the same piece of code using several different editors, each suitable for a different task. Some editors may use graphical or tabular notations, some may show extra information from other sources, while others may reduce the amount of visual clutter; and yet all can be tied to the same piece of code (AST). The developer can thus choose the best visualization of the code for the given task.
Use diagramming notations in combination with text – think of electrical circuits, for example, modeled as graphical schemes with embedded pieces of code attributed to individual elements of the scheme.
If it isn't text, how does the integration with version control work? Can I merge versions or show the difference between files?
Special support is needed for infrastructure integration. Since the concrete syntax is not pure text, a generic persistence format must be used. Therefore, special tools need to be provided for diff and merge features. MPS provides integration with version control systems, such as SVN or Git, and handles diff and merge functionality in the tool, using concrete projected syntax. Note that since every program element has a UUID, a move can be distinguished from delete/create, which provides more usable semantics for diff and merge. The picture below shows how the VCS in MPS looks like.
How long does it take to get used to the projectional editor?
Using the MPS projectional editor for the first time can feel odd because it is different from a textual editor. Our extensive UX research has shown that it takes a few days for most users to become accustomed to the projectional editor and feel no discomfort. In fact, many users have claimed they prefer the MPS way of editing things, since in many contexts you're selecting elements based on the syntax tree anyway.
How is MPS licensed?
MPS is an open-source product under the Apache 2.0 License.
How can I quickly get started with MPS?
How active is the community?
The community is small compared to those of other technologies, but it’s very active. Over the years, members of the community have been involved in different ways:
MPS.rocks is a curated list of awesome MPS extensions, libraries, and resources created and maintained by the community.
MPS has been the topic of a variety of academic papers, books, and conferences. Check out the MPS in Academia page to take a look at some of the great work that’s being done.
You are always welcome to join the Slack workspace to interact with or post questions to other members of the community.
Which languages does MPS include out of the box, for me to extend?
MPS comes with implementations of Java (version 1.8) and XML out of the box. A C implementation is available and supported by our official partner itemis. Other languages are being developed by third-parties and as open-source projects. Visit the MPS Languages Repository page for more details.
Is there a language repository?
Since languages can be packaged and distributed as jar files, nothing prevents languages from being shared the same way libraries are. A handful of language plugins (provided by JetBrains and third parties) for MPS as well as for IntelliJ IDEA are publicly available in JetBrains Marketplace:
Are there books on MPS?
Yes, a number of books and numerous academic papers have been written and published over the past years. We try to collect all of them and display it on our MPS in Academia page.
Are there any successful projects developed with MPS?
MPS is a mature product used in different industries, including electrical engineering, insurance, tax legislation, healthcare, and others. Companies such as Siemens, Bosch, Canon, and others are using MPS to implement powerful DSLs for their respective domains.
How well does MPS scale?
In a load test conducted by mbeddr, single-root elements (the equivalent of files in a classical IDE) could go up to 4.000 lines without serious performance issues. They have also measured that a C system with up to 100.000 lines of C code should work fine.
MPS is open-source, but still developed by JetBrains. How does that work?
JetBrains is the main contributor to the MPS project, providing more than 10 full-time developers. External contributions are welcomed, though, either as ideas shared through the forum, requests and bug reports in the tracker, or patches to the code. Regular contributors may become project committers and participate in the project planning and implementation process.
Can I import Java code into MPS?
MPS makes Java interoperability easy. For example, you can use any Java libraries in MPS with no problem. You can mix-and-match Java and MPS code on the same project, so your MPS code can see and use your Java code, and vice versa, in Java you can use the code generated from MPS. Also, MPS can parse snippets of Java code that you paste into MPS and can transform them into valid BaseLanguage code.
Which Java versions are supported?
MPS can run on JDK 17 and later. Visit the MPS Java compatibility page for more details.
Does MPS integrate with Java IDEs?
As a standalone application implemented in Java, MPS runs on all major platforms. MPS has an IntelliJ IDEA plugin to deploy languages. Language development is still done with the MPS standalone application, but language use is now possible in IntelliJ IDEA. This gives users much better options when integrating MPS-based DSLs into their Java and other applications.
How about Eclipse integration?
While technically feasible, integration with Eclipse is not actively pursued at this time. Depending on the interest among MPS users and their ability to contribute to or sponsor such activity, JetBrains is willing to consider implementing Eclipse integration.
How can I get support?
There is an MPS community forum and a Slack Community, where you can get support. An issue tracker is available for submitting and tracking bugs. Last but not least, you can also get professional support from those who have real hands-on experience with MPS.
How does MPS compare to other language workbenches?
Unlike most other language workbenches, MPS uses a projectional editor.
Also, MPS is one of the most comprehensive systems as it provides support for language structure, syntax, type system, constraints, refactoring, transformation, and code generation – all in a single integrated package.
The only way to form a better idea would be to try various language workbenches and consider the features and benefits of each in the context of your specific projects. That said, you may want to: