Code generation with MPS for the uninitiated and/or textually inclined

  1. You can switch on storing transient models to see how the generation progresses: this is switched on and off by the small “T” in the lower right corner of the MPS window.
  2. The “root” in root mapping rule means that the output of the template will be a root, not that it has to take a root as input.
  3. A mapping label must not only be defined but also populated. You do this by wrapping the node you want to be able to refer to in a $LOOP$ macro.
  4. Generation is an iterative process: it will iterate over the model before each generation step, and “shop around” in the generators of all languages involved (i.e., used or depended on) to see how to transform each root. Generation will stop when all output roots of a step are text, or when that condition wasn’t fulfilled for a certain number of steps — usually 10.
  5. Roots for which no transformation was found, are carried over to the next step.
  6. To prevent a root from making it into the next generation step, use an abandon root rule. It’s e.g. necessary to use this if you have root mapping rules that act on descendants of roots, but not for the roots itself.
  7. Mapping to text is done through a TextGen component. This is typically the last step in generation, which is why such a component maps only roots to files. Output cannot be “piped” to some other generation step, or equivalently: TextGen components cannot be called — instead, TextGen instances of concepts for which a TextGen component is defined are automatically picked up by the generator.
  8. Also, you can only have one TextGen component per concept. However, you can always create “dummy” concepts which wrap an instance of another concept as child, to create multiple files per instance.
  9. Having said that: if you feel you need to work around the limitations of TextGen, you might be trying things the wrong way. E.g., if you want to embed SQL statements, specified through some query language implemented in MPS, into Java code, you’d like to define TextGen components for the concepts in that query language and “call” these from the templates for the Java code.
    The right way to do this, would be to define an extension of BaseLanguage with an SQLStatement concept, instances of which can be plugged into the PreparedStatement.query(..) method. Now you can define a TextGen for SQLStatement which is then automagically picked up during generation.
  10. A template switch model can just have one, non-polymorphic case. As such, it acts as a simple function that you can call from another template using the $SWITCH$ macro.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Meinte Boersma

Meinte Boersma

All-round software value creator, specialising in DSL construction and language engineering.