I got a question about my recent post on Good and bad ways of exporting DSL models. Adrián Szegedi messaged me on the MPS Slack and wanted to clarify why I don’t recommend using the MPS generator to export models. He said it worked for him when he built a generator to export the MPS structure model to a set of Java classes.

His generator converted this concept:

concept VeryEmpty extends BaseConcept
                  implements IEmpty

instance can be root: false
alias: <no alias>
short description: <no short description>

properties:
first : string
second : integer
third : boolean
fourth : SomeEnum

children:
childo : VeryEmpty[0..1]
childos : VeryEmpty[1..n]

references:
refo : VeryEmpty[0..1]

into this code:

package EmptyLang.structure;

/*Generated by MPS */

import dummy.IEmpty;
import org.company.enums.SomeEnum;
import java.util.List;

public class VeryEmpty implements IEmpty {
  private final String first;
  private final int second;
  private final boolean third;
  private final SomeEnum fourth;
  private final VeryEmpty childo;
  private final List<VeryEmpty> childos;
  private VeryEmpty refo;


  public VeryEmpty(String first, int second, boolean third, SomeEnum fourth, VeryEmpty childo, List<VeryEmpty> childos) {
    this.first = first;
    this.second = second;
    this.third = third;
    this.fourth = fourth;
    this.childo = childo;
    this.childos = childos;
  }


  public String getFirst() {
    return this.first;
  }
  public int getSecond() {
    return this.second;
  }
  public boolean getThird() {
    return this.third;
  }
  public SomeEnum getFourth() {
    return this.fourth;
  }

  public VeryEmpty getChildo() {
    return this.childo;
  }
  public List<VeryEmpty> getChildos() {
    return this.childos;
  }
  public VeryEmpty getRefo() {
    return this.refo;
  }

  public void setRefo(VeryEmpty refo) {
    this.refo = refo;
  }
}

and it turned out to work very well. So why do I say that using the generator for exporting is problematic?

There is some confusion regarding the terms here. I would call what Adrián is doing translation, not export. What’s the difference?

Let’s say you have a tool that reads a model and produces some output based on what it reads. If the tool understands the semantics of what it’s reading and produces different output depending on that semantics then I consider it a translator. In Adrián’s case the tool knows what an AbstractConceptDeclaration is and what a LinkDeclaration is and it converts the concept declaration into a class whereas a link declaration is converted into a field with a getter and a setter.

If the tool would translate everything into the same kind of output, e.g. code to build a representation of a MPS node tree treating all nodes the same regardless of their concepts and meaning, then such a tool would be an exporter.

And my experience is that using the MPS generator language to write an exporter is going to be difficult for the reasons mentioned in the original post. Using the MPS generator language to write a translator, on the other hand, is perfectly fine and is exactly what the language was designed for.