Sometimes your MPS generator doesn’t generate what you expect. For these cases MPS has tools to help you pinpoint the exact misbehaving rule.
The Steps
When a generator doesn’t give you the output you expect, here is what you can do:
- Enable keeping transient models.
- Rebuild your model.
- Find the first transient model with the error.
- In the editor, select the incorrectly generated node.
- Right-click on the node and choose Language Debug → Show generation traceback in the context menu.
- Examine the traceback to determine the erroneous rule.
Troubleshooting Example
To illustrate these steps let’s have a look at how one particular problem can be debugged.
Let’s say we are creating a simple language for shopping lists and want to generate text files out of it. Instead of the rather complicated TextGen aspect of MPS we used the wonderful plaintextgen language.
The structure is very simple:
and the generator looks like this:
(This simplified presentation of generator macros is provided by Kolja Dummann’s excellent Durchblick plugin.)
Now we define our shopping list:
Shopping List Christmas Shopping
Tree : 1 pieces
Decorations : 5 pieces
Presents for the family : 10 pieces
And we expect to get this output when we generate it to text:
Christmas Shopping
------------------
- Tree:1
- Decorations:5
- Presents for the family:10
But when we check the generated output, it looks weird:
Christmas Shopping
------------------
- Tree:1- Decorations:5- Presents for the family:10
The whole list is written on one line instead of having a separate line per item.
Let’s use transient models and generation traceback to find out where the problem lies.
While transforming our model the generator goes through a series of steps, applying various mapping configurations and producing intermediate, so called transient, models. By default the generator throws them away at the end of the generation process, but we can tell MPS to keep them around.
Together with the transient models the generator also stores the generation trace, which is a kind of a log record containing information about the rules that were applied and what source nodes were translated into what target nodes.
Now let’s see how to use this information.
First, let’s tell MPS to keep transient models: Build -> Save Transient Models (or click on the pink square with T at the right end of the status bar).
Next, let’s rebuild our model and check the transient models:
We are looking for the first transient model in which things have gone wrong. In this simple case we only have two
models, the first one being a copy of the original model (suffixed by @0
), and the second one being the final
transformed model before the actual text generation took place.
We can see that the second model was generated incorrectly, the items are arranged horizontally:
Now is the time to apply the generation tracer tool. We can select the incorrectly generated fragment (the horizontal collection), right-click and choose Language Debug → Show generation traceback.
What we see is a tool window with a tree that we can expand:
The tree shows how our node was generated: the root is the input, the children nodes are the mapping rule and the resulting node. Each node in the tree is clickable. Clicking on the rule (the node with the gear icon) will bring us to our root mapping rule:
The rule by itself doesn’t tell us anything, we need to click through to the map_ShoppingList.txt
template (already shown above but repeated here):
Now after staring a bit at this template we see that the $COPY_SRCL$
macro is placed on a node inside a horizontal
line. This means that when this macro is applied to a list of nodes, the results will end up inside this horizontal
line, so they will be stacked horizontally. To correct this, we need to remove the macro from the word and place it on
the entire line instead:
Note that the $COPY_SRCL$
macro now hides the end-of-line symbol from plaintextgen, indicating that it’s now part of
the vertical collection of lines, and multiple nodes will be generated into multiple lines.
After rebuilding the project, the generated output is now finally correct:
Christmas Shopping
------------------
- Tree:1
- Decorations:5
- Presents for the family:10