MPS 2023.3 Help

SModel language

The purpose of SModel language is to query and modify MPS models. It allows you to investigate nodes, attributes, properties, links and many other essential qualities of your models. The language is needed to encode several different aspects of your languages - actions, refactorings, generator, to name the most prominent ones. You typically use the jetbrains.mps.lang.smodel language in combination with BaseLanguage.

Treatment of null values

SModel language treats null values in a very safe manner. It is pretty common, in OO-languages, such as Java or C#, to have a lot of checks for null values in the form of expr == null and expr != null statements scattered across the code. These are necessary to prevent null pointer exceptions. However, they at the same time increase code clutter and often make the code more difficult to read. In order to alleviate this problem, MPS treats null values in a liberal way. For example, if you ask a null node for a property, you will get back a default value for the type of the property. If you ask a null node for its children list, you will get empty list, etc. If you call a behavior method on a null node, a null value is returned, provided the return type of the invoked method is a ClassifierType or a StringType. For a PrimitiveType, the default value of that type is returned. This should make your life as a language designer easier.

Operation parameters

A lot of the operations in the SModel language accept parameters. The parameters can be specified once you open the parameter list by entering < at the end of an operation. E.g. myNode.ancestors<concept = IfStatement, concept = ForStatement>.

The "+" symbol as a parameter to these operations means "include myself". That is, when the node, on which the operation is being invoked, matches the condition, "+" ensures that the node will also be included in the returned result - e.g. myNode.ancestors<concept = IfStatement, +> may return myNode, if it is an IfStatement.

Managing concurrent access

The jetbrains.mps.lang.access language eases the use of the model access API, namely its concurrent access part. You can think of this language as a syntax sugar on top of the model access API and examples are provided of corresponding low-level code that accesses the API directly.
To access MPS models, appropriate lock must be obtained by the thread, otherwise the read or write operation will not be permitted. The jetbrains.mps.lang.access language must be imported for these statements to be available The language contains the following commands:

  • write action with

  • read action with

  • command with

  • execute command in EDT with

  • execute in EDT with

  • undo-transparent command with

Example of obtaining a lock

Some kind of locks can only be obtained by EDT. The platform provides API to schedule a task to be executed in the context of EDT through the ApplicationManager class:

Example of scheduling a command on EDT

write action with

Synchronous model write:

Modifications to models can only be performed from within managed actions, which hold the appropriate write lock. The method obtains such a lock and executes the provided action. It should not be invoked from EDT (Event dispatching thread), otherwise, a UI freeze may occur. A lock cannot be upgraded. When owning the read lock, it is not allowed to ask for the write lock through this command.

read action with

Synchronous model read:

Querying properties of models can only be performed from within managed actions, which hold the appropriate read lock. The method obtains such a lock and executes the provided action.

command with

Synchronous model command:

It represents a write action executed with respect to the platform undo mechanism. This method should be invoked from EDT thread only. Unlike execute command in EDT, this method executes synchronously.

execute command in EDT with

Schedule command to run from EDT asynchronously:

It represents a write action executed with respect to the platform undo mechanism and runs asynchronously from EDT thread. This method may be invoked from any thread.

execute in EDT with

Schedule asynchronous model read from EDT:

Querying properties of models can only be performed from within managed actions, which hold the appropriate read lock. The method obtains such a lock and executes the provided action asynchronously on the EDT UI thread. Inside the action, it is safe to touch any UI elements and perform other EDT-bound actions of the IntelliJ platform.

undo-transparent command with

Undo-transparent command:

The executed code has model write access and is treated as a command. The only difference is that changes from the transparent action will be merged with that of the previous undoable command and so it will not be possible to undo this action separately.

Last modified: 07 March 2024