Hi, my name is Václav and I've created this tutorial for you. The tutorial is a living creature that I constantly maintain and evolve to make it better serve its purpose - to help you learn how to design languages with MPS.
You can help me on that mission - if you spot a mistake, hit a road-block or become confused - let me know. I'll be very grateful , if you leave a comment or file a YouTrack issue for me. Thank you.
- First of all, check out a two-minute overview video about MPS - Why JetBrains MPS, so you can assess whether this tool offers something that you need on your projects.
- Our new VoiceMenu demo application has been created to give people coming from different domains of expertise a quick understanding of the potential of MPS. Watch a short https://youtu.be/pVIywLXDuRo.
- JetBrains MPS is an efficient and reliable development tool that has been adopted by software vendors on both commercial and academic projects. MPS-based DSLs have been adopted in a wide range of domains, such as legislation modellingmodeling, electrical engineering, the insurance industry, embedded software, medicine systems, bio-informatics, and data analysis. The "How it works" page lists several of the successful projects and gives a high-level overview of the technology used.
You may also like to slow down a bit and read a few documents describing how people have succeeded with MPS. We've collected a few case studies that may inspire you to your own ideas on building something great around MPS.
Knowing keyboard shortcuts turns good developers into great ones. As you learn MPS you will internalize various key combinations that trigger useful MPS functionalities. There's one key combination that you should remember from the very beginning, though - Control/Cmd + Z. One again - Control/Cmd + Z. It is the Undo action. Whenever you either intentionally or by mistake do something wrong and you want do to get back to functional code, turn to Control/Cmd + Z.
Now you must be curious about how the robot sample language has been created. Please, open again the Robot Kaja sample project and play our explanatory screen-cast showing you round the language definition fundamentals. As you go through the video, pause frequently and look around the sample project yourself. This way you will understand a typical language structure and see the relationships between its individual parts.
At this point, you should understand that language definition consists of several aspects. Some of these are mandatory, some are optional:
- Structure - Defines the kinds of nodes (called Concepts) that may be used in user models. Each node in the program (model) refers to its concept. Concepts specify, which properties, children and references nodes may have. Concepts can extend other Concepts and implement ConceptInterfaces.
- Constraints - Restricts the relationships between nodes as well as the allowed values for properties beyond the rules defined in Structure. Constraints typicaly typically define:
- the target scope for references (a collection of allowed nodes a reference can point to)
- situations, in which a node can be a child/parent/ancestor of another node
- allowed values for properties
- property accessor methods (getters and setters)
- Behavior - Just like classes in OOP hold methods, Concepts may define methods and static methods that can be invoked on nodes in a polymorphic way. Nodes thus carry behaviour carry behavior alongside their properties and relationships.
- Editor - Instead of defining a parser that would translate code from an editable form (i.e. text) into the tree-like structure that a computer could manipulate, MPS offers the concept of projectional editor, which let's the user edit the AST directly. The Editor aspect enables language designers to create a UI for editing their concept concepts.
- Actions - Since the MPS editor manipulates the underlying AST directly, some editing actions, such as copy-paste or replacing one node with another one translate into non-trivial AST changes. The Actions aspect holds definitions of such customised AST transformations.
- Intentions - All modern IDEs assist developers with instant code manipulating action available under a handy key-shortcut (Alt + Enter in MPS). Language authors can define such little code transformations for their languages in the Intentions aspect.
- Typesystem - Language that Languages need to type-check their code need to provide type-system rules. The MPS type-system engine will evaluate the rules on-the-fly, calculate types for nodes and report
errors, wherever the calculated type differs from the expectations.
So called checking rules may additionally be defined to verify non-typesystem assertions about the model.
- Dataflow - The ability to understand the flow of values and the flow of control through language constructs helps languages report issues such as unreachable code or potential null-pointer error. Language A language designer can leverage the Dataflow aspect to define the flow for each concept, which MPS will then use to calculate the dataflow for the whole program.
- Generator - Models written in one or more languages get ultimately translated into runnable code in some target general-purpose language and platform, such as Java. Along the way models get gradually transformed so that repeatedly concepts get replaced with concepts from a lower level of abstraction until the bottom-line level is reached. The rules for translating concepts and their proper ordering is defined in the Generator aspect.
- TextGen - During code generation after the Generator has reached the bottom-line AST representation, the TextGen phase kicks in and translates all nodes in the model into their textual representation and saves the resulting textual source files on disk.
When editing code in MPS you will run into situations when your coding habits interfere with the projectional nature of the MPS editor. I'm actually pretty confident that you have already discovered such surprises during your experiments. Code The code in MPS is not text, but instead, it is a projection of the abstract syntax (AST). This gives several benefits to language designers and, at the same time, makes the editing experience slightly different and more-restrictive than in the commonplace text editors. This may or may not be considered to be an advantage, nevertheless, there is a learning curve to projectional editing. In general, in projectional code you more rely on the assistance of the editor. Code-completion, block selection, and intention actions should become your close friends in order to become an efficient projectional coder. There's a good and a bad side to it:
We summarized the core essential tips on how to leverage the projectional editor. Please, check out the Commanding the editor page and keep it ready when making your first steps in MPS. Although you do not have to memorise memorize all the keyboard shortcuts immediately, they will certainly make your coding more efficient once you start developing your own projects.
Beware, you are entering a "Suck Zone" here. We're happy to see you here, but you need to be warned that the road gets quite steep and more bumpy bumpier as you progress through the Calculator tutorial and the following exercises. No wonder, you'll be doing real language design now and you'll be left intentionally on your own to implement parts of the languages. If things do not work out for you, relax, step back and try again. Sometimes the problem may be as small as a semicolon missing from selection or a method placed in a wrapper class instead of an anonymous inner class. Remember, you can always ask for assistance on the forum and we'll help you get back on track.
Congratulations! By completing the above tutorials and exercises you've made a serious dent into the language design world. Your knowledge and command of MPS could now be qualified somewhere above the Advanced beginner stage of the Dreyfus model of skill acquisition. This is definitely a good time to celebrate and perhaps also to let us know about you your success.
The MPS team offers hands-on training. Check out the details:
Moving up the ladder
The next stage in the Dreyfus model of skill acquisition is Competent. Once you reach that stage you'll be able to work on your own without concrete guidelines and supervision. But for this to happen, you'll need to spend more time solving various problems with MPS. If you already have an idea of a language to implement, go ahead and do it. If not, try to come up with a useful little language. You could as well try to re-implement one or more of the MPS samples and then see how closely close you got. Or just pick a sample as the starting point and move it forward - add language features, implement a generator, add type-system rules, polish the editing experience - whatever feels like the right challenge for you.
After becoming Competent you should definitely continue gaining experience. The more you work with MPS and the more divert your projects are, the faster you'll be moving up on the Dreyfus model of skill acquisition scale. If you set yourself a goal to become Proficient and ultimately an Expert in MPS, you might consider trying:
- Studying and practising practicing advanced topics, such as:
- Helping MPS expand into there areas by creating a base language for a different target language/platform - Python, Ruby, Dart, Haskell, Go, etc
- Speaking about MPS at events
- Helping us evolve the documentation
- Contributing code to the MPS project
Over time the MPS team has created a large collection of screen-casts covering many aspects of MPS use and language design. You may check them out all nicely sorted at the MPS screen-cast page or directly at the MPS channel of JetBrains TV.
The MPS team offers hands-on trainings. Check out the details:
The MPS documentation page will give you all the remaining pointers to case studies, tutorials, FAQs and other pieces of MPS documentation.
- SampleJavaExtensions - a collection of small handy Java enhancements, such as parallel for loop, unless statement, Money literal, decision tables and Constants definition. The sample will teach you how to extend existing general purpose languages with custom constructs. You may also like to watch a short screen-cast introducing the individual extensions.
- Complex - defines a Java extension to work with complex numbers
- XML Literals - allows XML literals to be used directly in Java code as first-class language elements. The language builds on top of jetbrains.mp.xml and generates into into into org.jdom.* API. The user-inserted XML code may refer back to the surrounding Java context to easily parametrize.
- math - provides fancy-looking math language extension to Java, which allows you to enter complex numbers, matrixes, intervals, summation, product and other common mathematical operations in a natural way.
- LanguagePatterns - a set of sample languages illustrating implementations of common language patterns in MPS. It is useful for beginners to see in isolation concrete implementations of typical language constructs. This sample project is gradually being updated with new patterns.
- MultipleProjections - an example of a simple state machine language that focuses on the mechanism of multiple projections per concept. The programmer, who uses the language, can on-the-fly switch between several pre-defined notations as she progressed with her state-machine definition. All the available notations are defined in the language or its extensions.
- MultiTarget - illustrates how to have a single language generated into multiple different target languages.
- Custom Aspects - shows the ways to define custom aspects for language definition. Check out the Custom language aspect cookbook for details.
- Cross Model Generation - illustrates how to use custom generator plans to achieve cross-model generation.
- Component Dependencies - a minimalistic example of a language for expressing dependencies between components of a system, which provides three alternative editor notations:
- Customized Debugger - an example of hooking a languages language with the Java debugger, even when the language neither extends nor generates into BaseLanguage.
- Mind maps - an intuitive example of defining a diagramming notation, including a set of customized graphical symbols
- State machine (Secret Compartment language/DSL book sample) - an example of a state machine language, including a state machine test language. An overview screen-cast is available to help you get started.
- The Simplest Language - a minimalistic example generating a Hello world application printing out a customized message. Shows the very basics of language generation.
- Migrations - a simple example of migration scripts to migrate two interconnected languages using both the smodel API and TransformStatement.
- Lambda Calculus - a language simulating lambda calculus, with projectional editor and generation into Java
- Agreement - an example of a business-oriented DSL
- Expressions - a simplified expression language to allow you to play with the type system and the Type-system Trace tool. The language gives you a bare-bone expressions language with minimal editor support, but with well-structured type-system rules, which you can help you learn the core of how MPS calculates types. Read more in the Typesystem Debugging documentation.
- Fixed Length Reader - illustrates how to create a language for describing binary data formats. Comes with a stub for a hypothetical runtime library that would extract elements from binary data using the supplied data format description (called configuration).
- HighLevel Languages - an example of defining a custom set of language definition languages. Illustrates how to define your own way to codify structure and editor for a language.
- Sample Language - A very intuitive and minimalistic example showing how to implement a common pattern of a root concept containing definitions as well as references to them. In this sample, we simulate Java classes, method definitions, and method calls. However, such a pattern is quite frequent in many languages and it is worthwhile to spend some time investigating. You may also check out a brief screen-cast showing you round this sample.
- Formula Language - a sample definition of an expression language, including editor actions and a generator
- NotesOrganizer - a sample DSL plugin for IntelliJ IDEA including a build script, that simulates a task/todo list. Tasks can have different priorities, states, and categories, which by themselves can also be customized. The task lists can be filtered using several kinds of Swing UI components and the user can choose among several alternative visualizations of the task lists. Shows as an example of filtering node collections, alternative editors and direct incorporation of Swing components into form-like notations.
- State Chart - an example of a state-chart definition language that generates state charts in the SCXML standard.
- Requirement Tracking (new) - an example of a universal, language-agnostic requirement tracking language. Goals of a software project can be captured in specification documents written using the provided requirement tracking language. Mentions of relevant requirements can be inserted into the code at places that implement these requirements. The mentions can be used in code that uses any MPS language. The sample features Node Attributes, non-trivial scoping and multiple switchable editors for a single concept.
- Attributes - a sample illustrating the transparent handling of attributes in text-gen and the generator. The two CommentAttribute node attribute concepts are passed through the generator unchanged so that their text-gen can convert them to text.
- Sample Facet - illustrates a simple make facet that intercepts the make process.
- Lightweight DSL - examples of usages of the jetbrains.mps.baselanguage.lightweightDSL language to build internal "lightweight" DSLs embedded into BaseLanguage classes.
- Heating controller - a simple language providing two notations to specify heating plans for a hypothetical home heating controller. The default notation allows for textual representation, while a language extension provides an alternative tabular notation.
- Progress Indicator - a set of actions that illustrate the proper way to handle progress bars in actions, how to make actions cancellable and enable them to run in the background.
- xmlPersistence - a non-trivial example of implementing custom persistence using the new Open API. The plugin contains three solutions (a build script, a persistence implementation, and a plugin descriptor). The custom persistence implementation will load/save XML documents. Please check out our Custom Persistence Cookbook for details.