Transformation menu language : How to understand work principles?

Good evening.
I would like to understand how new "Transformation menu language" works and I ask some help.

Input data:
I have three types of node: Parent, Child, Interface + BaseConcept concept.
I would like to change matching text and/or description of substitution menu for all of concepts.
But I don't understand how to do with even with help of user documentation.

Documentation link:
https://www.jetbrains.com/help/mps/transformation-menu-language.html#substitutemenu(default)

As I understand, there are some statements:
1) Default substitutions menus should has effect on ALL child concepts
Quote: "It also has effect on sub-concepts of the concept, unless these sub-concepts define their own..."
Expectation: If I define "wrap substitute menu" for BaseConcept or Parent -> I can change child behavior
Actual: I still have default substitution menu.
Addition: I don't understand the difference there between "for BaseConcept" and "for Parent".

2) Default transformation menu should has effect on ALL not overridden child concepts
Quote: "If the language designer does not provide one explicitly, a transformation menu defined for the closest super-concept"
Expectation: If I define "wrap substitution menu" for BaseConcept or Parent -> I can change child behavior
Actual: I still have default substitution menu.
Addition: I don't understand the difference there between "for BaseConcept" and "for Parent".

3) Should I always include substitute menu to transformation menu?
Quote: "if you want to assign the substitute menu to a particular cell of an editor, you will need to include your substitute menu in a transformation menu, because only transformation menus can be attached to editor cells"
Expectation: If I include default substitute menu for Parent / BaseConcept something will change =)
Actual: Substitute menu is still the same

4) Can I set default substitute menu / transformation menu for all cells of particular concept?
Expectation: If I set "Default menu for Parent" i will see changes
Actual: Substitution menu is empty Oo

So I decided to ask to help me to understand how it should work and why =)

Picture of my concepts:

1 comment
Comment actions Permalink
It has been a long time since this question was posted but others may come here looking for more information so I thought I'd write a few words. I admit I am confused with regards to what the structure of your concepts is: you mention Parent and Child but seem to imply that these are not parent/children but rather superconcept/subconcepts, and then your screenshots mention TranslatedConcept and SomeConcept but it's not clear how and where they are supposed to be used. Given my confusion, this will be a generic reply without regards to your particular situation.
 
First, we need to define and clear up some terms.
 
Given this concept declaration from BaseLanguage:
concept ExpressionStatement extends Statement

children:
  expression : Expression[1]
ExpressionStatement is a subconcept of Statement. Statement is its superconcept.
 
ExpressionStatement defines a child (containment) link ExpressionStatement.expression whose target concept is Expression. The actual child node can be any subconcept of Expression. The node of the concept ExpressionStatement will then be its parent node. The containing link of the child node will be Statement.expression. I'm writing this mainly because I'm going to use the terms below and it's important to 1) avoid confusion between super/subconcepts and parent/children concepts, and 2) know what "target concept of a containment link" means.
 
Another terminology excursion concerns menus. I will use the terms transformation menu definition and substitute menu definition to represent the menu definitions that you write in MPS. I will call the actual menu that gets built when you press Ctrl+Space the completion menu. A menu definition in my dictionary is something you write in MPS whereas a menu is something that MPS builds at run time based on all the definitions it knows about.
 
Now, to the points:
 
Ad 1) It's important to understand that when substitute menu definitions are looked up, the input to the lookup algorithm is not the concept of the existing node but rather its containment link. It's the "place" in the AST that is important, not the node that is currently occupying the place.
 
I'll give an example. Consider an instance of that ExpressionStatement concept from BaseLanguage that I showed above. Let's say it has an AssignmentExpression inside, so the AST is `a = 5;`. If I want to replace (substitute) the AssignmentExpression inside of ExpressionStatement with a different node, what are my options? The answer is, any Expression. Why? Because that's what the target concept of the ExpressionStatement.expression containment link is. Notice that it doesn't matter if the actual expression is an AssignmentExpression or a DotExpression or even absent. The current node  is irrelevant for the purpose of finding the relevant substitute menu definitions.
 
Most concepts will implicitly use a substitute menu definition that contains:
  1. an action for creating a node of this concept, unless it's abstract
  2. an instruction to include the default menu definition of all subconcepts of this concept
As a result, when building a menu for Expression, MPS will traverse its subconcepts and include them in the menu as well. But note that superconcepts are not considered. A completion menu for ExpressionStatement.expression will not contain entries from the substitute menu definition of BaseConcept because an instance of BaseConcept can't go there, only an Expression can.
 
Ad 2) Transformation menu definitions compose in the opposite way from substitute menu definitions. Since the idea is that we want to transform an existing node, we look at its concept and go look up the transformation menu for it. If no menu is defined MPS will fall back to the default menus for the superconcepts (since an instance of a concept can also be considered instance of any of its superconcepts per Liskov substitution principle). Note that if you write a default transformation menu definition then the fallback behavior does not apply and you need to specify it explicitly (using `superconcepts menu` instruction).
 
If you look at the default transformation menu for BaseConcept, called BaseConcept_TransformationMenu, you'll see that it includes the default substitute menu for the current link.
 
Tip: if you have unexpected entries in your menu you can use Ctrl+Alt+B (Cmd+Alt+B on Mac) to open the Menu Tracer tool which will give you a trace of how the item got to appear in the menu.
 
Ad 3) It's not possible to attach substitute menu definitions directly to editor cells, you have to include them in a transformation menu first. The default substitute menu definition is already included in the default transformation menu definition for BaseConcept so you might not need to do this if you only work with default menu definitions.
 
The completion menu is built from transformation menu definitions. If a definition says "include this substitute menu definition" then it gets included, otherwise it doesn't.
 
Ad 4) It's not possible to assign a transformation menu definition to every cell with one fell swoop but you can do it manually. The menu in the question is probably empty because the transformation menu for TranslatedConcept only includes the substitute menu for TranslatedConcept which only recursively includes a wrapping of itself so there are no actual entries besides menus including each other. MPS watches for endless recursion in the menus so it won't crash or hang in this situation but there are no menu items to display.
 
Closing tip: All these menu definitions are in fact quite low-level and a lot of work. Use grammar cells from MPS-extensions for a much better language design experience. Grammar cells are documented in a paper: http://mbeddr.com/files/gc-sle.pdf
2

Please sign in to leave a comment.