Introduction
MPS is an environment for developing programming languages on the Intellij Idea platform. It provides the ability to simulate programming languages, describe structures, focusing specifically on design and business logic, without being distracted by parsers, lexers, and various third-party language features. What you need to immediately designate: a language that is developed with the help of MPS is not compiled into a work program. Most often it is generated in a model of other languages or in text form.
Why did I decide to write this post? I believe that this is a very undervalued opportunity, and it is underestimated because the threshold of entry is very high, plus it is one of the most unpopular products of JetBrains.
The documentation is very detailed, describes all the possibilities, but if there is no awareness of “what am I doing and why should I do it,” then it is unlikely to be useful. There is also a series of lessons from
JetBrains on YouTube , but again, I more or less began to understand what is happening, only after two views of the entire series and a thorough study of the proposed sample projects.
')
I plan to write a series of posts about this wonderful environment, so that at the end of the reading enthusiasts have as few questions as possible “how to make this thing”, and as much as possible understanding of the structure so that you can effectively use the
documentation . We will learn MPS during the creation of a language for describing weather patterns. Why not strictly speaking?
Concept
MPS (hereinafter - the / MPS environment) provides the ability to create modules of two types -
Language and
Solution . The first is a description of the language and its
aspects , the second is used to develop any projects, test the language / languages, language extensions.
I will start with
Language .
The most important thing to understand from the beginning is the process of developing a language and what happens next to it.
- We describe the language model and the necessary aspects of this language, for example, the type system, the behavior in the editor.
- We describe how our language model is compiled into text or into a model of another language.
- We compile our language into a plugin for Intellij Idea and use it. All transitions from one model to another are made for us, as a result we get ready-compiled code.
It should be noted that writing code in the MPS format is slightly different from writing the text of the program, because we are actually editing AST (Abstract Syntax Tree), and what we see in the code editor is the projection of AST.
So, 1 article - 1 piece of the final project.
Create a project in MPS
At this stage we choose the name of the project and the name of the language, you can also create a Sandbox solution - a module in which we will look at how our language works.
We have an empty project. Totally empty. But in the WeatherPrediction language there are nested directives - structure, editor ... These are
aspects of the language - in them we describe the behavior of the language in different situations. For example, the
structure contains the basic
concepts of the language, and the
editor is how they will be displayed in the code editor. This should sound very abstract, especially if you are not familiar with MPS. Understand. So immediately into battle.
First we need to declare the
root concept of the language. Translated into Russian, we create a certain structure that will generalize all other structures. In Java, this would be
Java root concept example To create a concept, poke paint on WeatherPrediction -> New -> Concept.
A concept has 3 types of data that it can contain:
- properties - here you can store any primitive data, ala strings, numbers and boolean. An abstract example is an integer variable, which should have name: string , value: integer , final: boolean
- children - elements of other concepts are stored here. As an abstract example, for the Program concept there could be shoved an array of Statement
- references - links to other implemented concepts in the AST that are in the current scope are stored here. An abstract example is a variable whose value is a link to another variable by name (in reality, this is not quite the case, but this is an abstract example).
Let's call it PredictionList, define it as
root concept and inherit the
INamedConcept interface.
What happens here: We define the concept, call it PredictionList, say that it can be implemented as a root concept and inherit from INamedConcept. If you look at its definition
(Ctrl + B)then we will see that this is an interface concept that has a property name: string, which, strictly speaking, is logical from the name
Note that the syntax is similar to a programming language. It is this way: this code is written in the language
jetbrains.mps.lang.structure , which describes the concepts of the language.
If we now compile the project and want to see what happened, we will need to create a model in the WeatherPrediction.sandbox module.
LKM on
sandbox (generation required) -> New -> PredictionList
Replace
no name with Saint Petersburg
Boom! We have a default visualization of the concept. To view the AST, click on any place in the editor and press the hot
key Alt + XThe structure of everything is visible here, it is very cool and it is convenient to monitor the state of the tree. We immediately see that the name of PredictionList = Saint Petersburg. So, this is very cool, but we want everything to be beautiful, so we open the PredictionList concept editor and create an
editor aspect for it . Click on the green plus sign in the lower list, right below the code of our concept, select
Editor ->
Concept EditorHere we can describe how our PredictionList will be displayed in the code editor.
Until we go into details on how this is all done, just write
[- and we create an array of cells. It's simple: in each cell there is some kind of constant text / property / reference / children. And yes, the mapping is described in another language -
jetbrains.mps.lang.editor .
We want our list of weather predictions to look like this:
Weather prediction rules for% name% .
So we write.
In the first cell - the constant text, in the second -
{name} , a call to the property by the name key.
We rebuild our language (Ctrl + F9) and look in the Sandbox solution, where we previously created an empty PredicitonList named Saint Petersburg.
Everything works, AST is the same as before our modifications.
I’ll probably stop at this for now to get feedback. In the next post I plan to add a couple more concepts, as well as the generation of Java code.
Thanks for attention! Please, all wishes, misunderstandings and questions and write in comments. If the questions are specific and simple, I will answer in the comments, otherwise I will add to the next post.