Template switch macro Follow
Hi there,
I recently attempted to learn to use MPS by means of writing a simple language and generating java classes from it. I'm stuck at the following problem, which I thought could be solved with the "switch" macro, but I couldn't figure out how to make it work. There doesn't appear to be any documentation available on this macro, and there are only a few examples that use it. Unfortunately, one can scarcely guess how this macro works by simply looking at the examples. So, I would really appreciate if someone explains how to use them in a few words.
So, the problem I'm trying to solve is generating a tree-like structure from a source tree, using recursive templates. It's best described by an example:
E.g. for something like the following in XML:
One would write a corresponding transformation in XSLT similar to:
A( , ) B() C()
Which should produce
A(B(),A(B(),C()))
Now, how do I achieve the same result in MPS? My thought was I could employ the switch macro for this task, since it's the only tool I found that allows me to call templates recursively. Please correct me if I'm wrong and there is another, simpler and more elegant way.
I believe, one could simply create mapping from source nodes to templates and just run a substitution (AKA transformation) with the root source node. This would be most natural, but unfortunately it's unclear how one achieves this mapping.
Thanks in advance.
Regards,
Fedor.
Please sign in to leave a comment.
Hi Fedor!
To generate nodes recursively we use combination of ‘reduction rules’ and $COPY_SRC$ macro (or $COPY_SRCL$ macro).
In course of generations, if the $COPY_SRC$ is encountered, then generator tries to find and apply a ‘reduction rule’. If applicable ‘reduction rule’ is found and it also contains $COPY_SRC$ macro then the same procedure is repeated. This provides a way to make a recursion.
I’ve attached sample project containing simple source language (myxml) and generator from it to baseLanguage (java).
The generator contains single reduction rule which is applicable to any Element in source model and which reduces an Element to a static method call which will look like:
element(“A”, new String[]{ element(“B”,..), .. })
Igor.
Attachment(s):
recursivegen_myxml_java.zip
Hi,
thanks Igor, this appears to be exactly what I require. However, I'm stuck at another problem, the generator throws an exception in a seemingly legal situation:
ERROR - mps.generator.GeneratorManager - Exception
java.lang.ClassCastException: jetbrains.mps.baseLanguage.ExpressionStatement
at jetbrains.mps.baseLanguage.ReturnStatement.getExpression(ReturnStatement.java:19)
at jetbrains.mps.baseLanguage.textGen.ReturnStatement_TextGen.doGenerateText(ReturnStatement_TextGen.java:16)
at jetbrains.mps.textGen.TextGenManager.appendNodeText(TextGenManager.java:49)
at jetbrains.mps.textGen.SNodeTextGen.appendNodeText(SNodeTextGen.java:24)
at jetbrains.mps.baseLanguage.textGen.StatementList_TextGen.doGenerateText(StatementList_TextGen.java:20)
at jetbrains.mps.textGen.TextGenManager.appendNodeText(TextGenManager.java:49)
at jetbrains.mps.textGen.SNodeTextGen.appendNodeText(SNodeTextGen.java:24)
at jetbrains.mps.baseLanguage.textGen.InstanceMethodDeclaration_TextGen.doGenerateText(InstanceMethodDeclaration_TextGen.java:43)
at jetbrains.mps.textGen.TextGenManager.appendNodeText(TextGenManager.java:49)
at jetbrains.mps.textGen.SNodeTextGen.appendNodeText(SNodeTextGen.java:24)
at jetbrains.mps.baseLanguage.textGen.ClassConcept_TextGen.doGenerateText(ClassConcept_TextGen.java:115)
at jetbrains.mps.textGen.TextGenManager.appendNodeText(TextGenManager.java:49)
at jetbrains.mps.textGen.TextGenManager.generateText(TextGenManager.java:29)
at jetbrains.mps.generator.generationTypes.TextGenerationUtil.generateText(TextGenerationUtil.java:17)
at jetbrains.mps.generator.generationTypes.GenerateTextGenerationType.handleOutput(GenerateTextGenerationType.java:25)
at jetbrains.mps.generator.GeneratorManager.generateModels(GeneratorManager.java:319)
at jetbrains.mps.generator.GeneratorManager$3$1.run(GeneratorManager.java:214)
at jetbrains.mps.ide.command.CommandProcessor.executeCommand_internal(CommandProcessor.java:85)
at jetbrains.mps.ide.command.CommandProcessor.executeCommand(CommandProcessor.java:71)
at jetbrains.mps.ide.command.CommandProcessor.executeCommand(CommandProcessor.java:48)
at jetbrains.mps.generator.GeneratorManager$3.run(GeneratorManager.java:212)
I attach my small project here, could you take a look if you have time?
Thanks,
Fedor.
Attachment(s):
Qlog.zip
So, I figured out what the problem was.
Simply put, the "template fragment" braces of the template referred from the $COPY_SRC$ macro were introduced at the ExpressionStatement node, which is a parent of InstanceMethodCall. Apparently, the template fragment should be introduced instead at the latter node. Unfortunately, one can not distinguish between the two cases by simply reading the screen: visually they look absolutely the same.
Thanks anyway, MPS is a great toy!
Thanks for feedback!
Incorrect positioning of a template-fragment is common yet not easily detectable error.
Certainly we need improvements on the matter.
Igor.