Convert Node into Super Concepts Node

Hi.

I've got a Concept let's call it 'ExtensionClass' which is extending base language's 'ClassConcept'. 'ExtensionClass' does only provide some additional Constraints and Behaviour, that are not relevant for the generator.

I tried to not use a root mapping rule, hoping that 'ClassConcept' rule will be applied. But it didn't. So i created a root rule which used the '$INSERT$' to create a node of 'ClassConcept'.

But the problem is the creation of such a ClassConcept-node. It seems like that it's not possible to cast a node to a node of another (super) concept. The only way to me was to create a new node<ClassConcept> and to copy relevant information from my 'ExtensionClass' to the new node.

It works but is there a more elegant way to convert a concept node to a node of its super concept?
Alternatively: Is there a way to use the super class' generator/rule in my root rule?

7 comments
Comment actions Permalink

Hi,

did setting the "inheritors" flag in your mapping rule for ClassConcept help have the rule applied to the subconcept?

Use the "node cast" (aka :) operator to cast nodes, e.g. "myNode:ClassConcept.x", although I don't think you ever need to cast to a super concept, since nodes of a sub-concept are always valid instances of the super-concept.

Vaclav

 

0
Comment actions Permalink

Maybe i don't get it but i don't have a mapping rule for class concept as it is integrated in base language.

So my 'ExtendedClassConcept' extends 'ClassConcept'. When not adding any rule for 'ExtendedClassConcept' in my mapping configuration nothing gets generated. So i need to apply a mapping rule. Setting the flag there doesn't make sense to me.

When returning the 'node:ClassConcept' in an $INSERT$ for my extended class concept results in an infinite loop. It seems that it's applying the 'ExtendedClassConcept's rule neverthless, even after casting.

0
Comment actions Permalink

Ok, so you did not create any mapping rule for ClassConcept. In that case we are talking TextGen here, since ClassConcept does not have a mapping rule by itself, as it is not generated into any other concepts.

The rules of TextGen mandate a TextGen to be specified for subconcepts explicitly, the TextGen rules of super-concepts are not applied to sub-conceps unless instructed so in a TextGen rule of the subconcept.

So you can either create a mapping rule for ExtendedClassConcept to generate ClassConcept or create a TextGen definition for ExtendedClassConcept and specify "use textgen of ancestor".

Vaclav

 

0
Comment actions Permalink

Thanks for clarification.
But now i run into an exception.

java.lang.NullPointerException
at jetbrains.mps.baseLanguage.textGen.BaseLanguageTextGen.fileHeader(BaseLanguageTextGen.java:139)
at jetbrains.mps.baseLanguage.textGen.ClassConcept_TextGen.generateText(ClassConcept_TextGen.java:28)
at jetbrains.mps.text.impl.TextGenTransitionContext.generateText(TextGenTransitionContext.java:61)
at jetbrains.mps.text.impl.TextGenSupport.doAppendNode(TextGenSupport.java:153)
at jetbrains.mps.text.impl.TextGenSupport.appendNode(TextGenSupport.java:149)
at jetbrains.mps.text.impl.RegularTextUnit.generate(RegularTextUnit.java:168)
at jetbrains.mps.text.TextGeneratorEngine.lambda$schedule$1(TextGeneratorEngine.java:105)
at jetbrains.mps.smodel.ActionDispatcher.dispatch(ActionDispatcher.java:85)
at jetbrains.mps.smodel.WorkbenchModelAccess.lambda$runReadAction$0(WorkbenchModelAccess.java:89)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:796)
at jetbrains.mps.smodel.WorkbenchModelAccess.runReadAction(WorkbenchModelAccess.java:86)
at jetbrains.mps.smodel.ModelAccessBase.runReadAction(ModelAccessBase.java:54)
at jetbrains.mps.smodel.ModelReadRunnable.run(ModelReadRunnable.java:46)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

Which is line

ctx.registerDependenciesOf(cls)

so

ClassifierUnitContext : ctx new  ClassifierUnitContex

seems to be null?

0
Comment actions Permalink

Indeed, the ClassConcept's textgen does define a context declaration, which has to be initialized in your textgen. So for your concept to generate correctly you have to add a few more things to the textgen.

Create a textgen component with a declaration in it that has the same name as the one in BaseLanguage's textgen.

Define a layout and refer to the context object declared above.

Having said that, ClassConcept's textgen was not created with the possibility to extend it in external languages in mind. Using the generator provides better flexibility when it comes to BaseLanguage extension.

1
Comment actions Permalink

Thanks. It is now working as i wish.

Is there a reason why I should create the TGComponent instead of using the BaseLanguageTextGen.ctx?

context objects : BaseLanguageTextGen.ctx : ClassifierUnitContext
0
Comment actions Permalink

Since BaseLanguageTextGen.ctx resides in another model, the reference crosses the model boundaries and cannot be generated properly without a generator plan. The issue of cross-model references is detailed here - https://www.jetbrains.com/help/mps/2020.1/generation-plan.html

Vaclav

 

1

Please sign in to leave a comment.