What is the application order of rules in generator templates?

  • 7
  • 42

I've many time recognized that I haven't really understood the order MPS applies the rules of a template. That is why my generators now consists of many templates with sophisticated priorities.
And now again I want to implement the following:
  1. A root node a of concept A should be transformed to a node b of B. But root node a should be kept in the model. There will be just one node of A in each model.
  2. For each node c of C, which is no descendant of a, one node d should be generated to the subtree of b.
  3. Each node of concept C should be transformed to a node of E.

Is there any way to implement this with just one mapping template without any scripts?

My first approach was to put the functionality of 1 into a root mapping rule with a mapping label. The second step should done by a weaving rule, where the label is used to get weaving context. And the last step can be transformed by a simple reduction rule. But unfortunately the root mapping rule seems not to be applied before the weaving rule starts, since node b is not available as context. I've also checked this with printf-debugging. So I can't follow the order mentioned in http://confluence.jetbrains.com/display/MPSD25/Generator
Answered by Sascha Lißon
 
When you are mapping an input node to an output node, you have to provide the input node to query the output node using a label, even if there is only one possible output node. That means, you have to use get output by label and input instead of get output by label.

In your example write
genContext.get output NewB for (genContext.inputModel.roots(A).first);
I've added a sample project which implements this example. The generator fails in this version. Perhaps someone can provide a patch for it.

When you are mapping an input node to an output node, you have to provide the input node to query the output node using a label, even if there is only one possible output node. That means, you have to use get output by label and input instead of get output by label.

In your example write
genContext.get output NewB for (genContext.inputModel.roots(A).first);

Damn, that was easy! Thanks a lot!
I thought get output by label has the same function, but now I've seen that it is restricted to conditional root rules. With this modification the generation works fine. But the following warning is still left:
bad context for weaving rule: b is generated from a, while input node is from SomeRoot
What is the meaning of this? Should I just weave new nodes inside the same root node? How can I get rid of this message?

To support parallel and incremental generation, MPS does not allow to use a different root as the weaving target. You can use a $WEAVE$ macro in the template of the target instead.

I forget about the weave macro again. There is no documentation about it, isn't it? Where should I use it? In a reduction rule? And how can I define the context node. Perhaps you can tell me for the example.
Many thanks!

The weave macro works the other way around. You attach it to the context node and define the source nodes. The weaving template is the same.

In your example remove the weaving rule and attach a weave macro to the B concept of your root mapping template:

weaving_macro.png

Thank you very much! Now I've got it and I've seen that many of my recent generator templates are too complex!
But information about this macro should really be added to the user guide! For me it seems that it is more meaningful than the weaving rule.