Referencing to a class generated in another language/generator
- 117
- 18
- Dmitry Sidorenko
- 10/04/10
My scenario:
I have a "Document" concept. I defined a generator, which generates classes with names in this form: "class Document{ID}DAO".
In another language, in which I need to have Document{ID}Model which should have "static Document{ID}Model getModel(Document{ID}DAO dao)"
How can I do that? It seems that I have to use some kind of mapping label, but I can't find how to put one on generated class. Besides, it seems that labes are not exported from one generator to another.
- Dmitry Sidorenko
- 10/12/11
Anyone? This is still unresolved.
How do I reference from one generator to classes generated in another generator?
How do I reference from one generator to classes generated in another generator?
- Evgeny Gryaznov
- 10/23/11
The MPS approach to model generation is very similar to normal compilers. It should be possible to generate only a part of a project. In java you can compile only one source file, in MPS the smallest unit is a model.
If you generate one model, referenced models could be not generated yet. So you cannot rely on their output or intermediate models. Instead you should produce output given the very first existing input models.
There are many ways to achieve that goal in your own language. But the idea is still the same. The number of external nodes you need to generate a model is quite few. You probably don't need every existing model, but only ones you refer to. Besides, you don't need every node from that models except the "exported" or "public" ones. Talking about java, the only data you need about existing classes is their methods, fields and inner classifiers, i.e. an interface, not the implementation. The solution is to import this external APIs into our model in the beginning and process them along with the current model.
Let's consider an example. We have two models X and Y. The first one contains higher-level abstraction of classifier (like state machine). The later one refers to the first one.
Here is the reduction sequence:
X: ConceptA -> ConceptB -> Classifier -> java class
Y: ConceptARef -> ConceptBRef -> ClassifierType -> ref to class in .java file
If ConceptA and ConceptARef live in the same model, everything is clear. When they are separated there is a problem: we cannot refer to ConceptB from ConceptBRef. The target doesn't exist while we generate Y. It only appears in intermediate models of X. OK, we need to make this reference internal.
The obvious ways are:
1. Whenever you need to refer to ConceptB, copy it into the current transient model, as a root, but mark it somehow to delete at the last step (to avoid text generation). That is exactly what Java compiler does when you import external classes: it reads them (without method bodies, of course), stores their interface in the memory and probably processes them.
2. Create an internal reference concept, containing all required information about the target (method call can contain types for all parameters for example). For baseLanguage we created such internal concepts in generator-specific baseLanguageInternal language.
If you generate one model, referenced models could be not generated yet. So you cannot rely on their output or intermediate models. Instead you should produce output given the very first existing input models.
There are many ways to achieve that goal in your own language. But the idea is still the same. The number of external nodes you need to generate a model is quite few. You probably don't need every existing model, but only ones you refer to. Besides, you don't need every node from that models except the "exported" or "public" ones. Talking about java, the only data you need about existing classes is their methods, fields and inner classifiers, i.e. an interface, not the implementation. The solution is to import this external APIs into our model in the beginning and process them along with the current model.
Let's consider an example. We have two models X and Y. The first one contains higher-level abstraction of classifier (like state machine). The later one refers to the first one.
Here is the reduction sequence:
X: ConceptA -> ConceptB -> Classifier -> java class
Y: ConceptARef -> ConceptBRef -> ClassifierType -> ref to class in .java file
If ConceptA and ConceptARef live in the same model, everything is clear. When they are separated there is a problem: we cannot refer to ConceptB from ConceptBRef. The target doesn't exist while we generate Y. It only appears in intermediate models of X. OK, we need to make this reference internal.
The obvious ways are:
1. Whenever you need to refer to ConceptB, copy it into the current transient model, as a root, but mark it somehow to delete at the last step (to avoid text generation). That is exactly what Java compiler does when you import external classes: it reads them (without method bodies, of course), stores their interface in the memory and probably processes them.
2. Create an internal reference concept, containing all required information about the target (method call can contain types for all parameters for example). For baseLanguage we created such internal concepts in generator-specific baseLanguageInternal language.
- jbrownson
- 10/30/11
I've made several different attempts to implement 1 or 2 and am not having a lot of luck with either. They don't seem well supported in the system. Can we get a bit more detail on which mechanisms we should use to do this? Solution 1 sounds a little better to me than solution 2, but I've tried various attempts at both.
Ideally could you demonstrate using the simple example I posted in this thread the supported way(s) of doing this?
Ideally could you demonstrate using the simple example I posted in this thread the supported way(s) of doing this?
- jbrownson
- 11/09/11
Something interesting happened. Shortly after I posted the message on Oct 30 my main project I'm working on started just working with simply doing by-string ref lookups and none of the other techniques you mentioned (it hadn't been working in the same configuration before). I recently got in to some strange (seemingly) unrelated state where I couldn't build anything so I deleted all my _gen directories and tried building from scratch and now my by-string references aren't hooking up again and I'm back to being blocked by this problem.
Can you think of any reason they would have been working for the past week or so?
Can you think of any reason they would have been working for the past week or so?
- jbrownson
- 11/11/11
With some help from Markus Voelter I got the simple example I posted working in some respect by importing external references. I haven't yet figured out how to then delete those references just before textgen, but at least this should be enough to unblock me.
The thing I was missing was I needed to add a separate mapping configuration for the preprocessing script that imports the externals that happens before the main mapping configuration.
I've attached it for anyone interested: CrossModuleReferenceTest-importExternals.zip (171KB)
The thing I was missing was I needed to add a separate mapping configuration for the preprocessing script that imports the externals that happens before the main mapping configuration.
I've attached it for anyone interested: CrossModuleReferenceTest-importExternals.zip (171KB)
- daniel sti
- 10/13/11
Hi Dmitry,
i think http://code.google.com/p/mps-lwc11/downloads/detail?name=LWC11-MPS-Docs.pdf&can=2&q=
Page 36ff will help you ...
Best,
Dan
i think http://code.google.com/p/mps-lwc11/downloads/detail?name=LWC11-MPS-Docs.pdf&can=2&q=
Page 36ff will help you ...
Best,
Dan
- Dmitry Sidorenko
- 10/13/11
Dan, thanks a lot, very interesting reading. Will what they're suggesting it tomorrow.
- jbrownson
- 10/19/11
Did you have any luck? I'm trying a similar thing.
- Dmitry Sidorenko
- 10/19/11
No, it didn't work for me. I decided to dump all my concepts in one single module so far. But that's just temporary solution.
- jbrownson
- 10/16/11
Funny, I actually came here to ask this exact question to see the answer at the top of the list. I actually remember reading that passage in that tutorial when I was getting going w/ all this and not understanding what it was getting at, but now I do.
Wowzers on the solution though :p
Wowzers on the solution though :p
- jbrownson
- 10/19/11
On my Mac using 2.0.2 I'm modifying /Applications/MPS 2.0.app/bin/mps.vmoptions with "-Dmps.internal=true" and I'm still not seeing the "Stubs for Generated Code" checkbox as described in the tutorial. I've modified all of my references to link by name, and things continue to work if a module is self-contained, but if I start referencing things in other modules the references aren't getting hooked up. Is that checkbox still necessary? If so am I doing something wrong to get it to show up?
- Dmitry Sidorenko
- 10/19/11
I wasn't lucky too. Solved my problem by redesigning generated classes to be independent on variable names.
- jbrownson
- 10/19/11
Hrm, I don't think that's possible for my language. Did you even get the checkbox to show up?
- Dmitry Sidorenko
- 10/19/11
No, I don't see the checkbox. I do see new checkbox "Load classes with app classloader", so I know the option is in effect.
- jbrownson
- 10/19/11
I put together a simple project demonstrating the problem. You can build the "sandbox" module just fine, but if you try to build "sandbox2" which references things in "sandbox" you get errors. I have '-Dmps.internal=true' in my vmoptions as specified above and do not see the 'Stubs for Generated Code' checkbox in the advanced tab of my solution properties. Can you advise us how we could make the "sandbox2" module build?
CrossModuleReferenceTest.zip (74KB)
CrossModuleReferenceTest.zip (74KB)
- jbrownson
- 10/19/11
Btw, interestingly enough I can use "Preview Generated Text" and it produces the right stuff, but when I make it I get errors about not being able to hook up references
- daniel sti
- 10/19/11
Ok,
i m using the 1.5 version of mps. There i can set the mps.internal=true and i can select the generate stup for solution checkbox. Like described in the lwc11 guide, i can reference generated classes from other models then ...
Dan
i m using the 1.5 version of mps. There i can set the mps.internal=true and i can select the generate stup for solution checkbox. Like described in the lwc11 guide, i can reference generated classes from other models then ...
Dan
- jbrownson
- 10/19/11
Huh, it sounds like "support" for this technique may have been broken in recent versions, I posted a reply in http://forum.jetbrains.com/thread/Meta-Programming-System-552 pointing to this one.