How to get the Type of a generated ClassConcept-Instance
Hi,
maybe i'm blind at the moment, but i can't find the Type (ClassifierType) of a generated ClassConcept-Instance within the same run. I get the ClassConcept via Mapping-Label and can easily work with ClassConcept.superclass or one of the ClassConcept.implementedInterface... but where can i get the type of the generated class?
Thanks,
Mirko
Please sign in to leave a comment.
Hi Mirko,
Classes have no type, they are not expressions.
If you want to obtain a type of some node, though, you should use .type operation.
To get a ClassifierType with a given (node of concept) Classifier, you should first create a ClassifierType and then set its classifier link to given Classifier. This can be written either in smodel language or using quotations.
Regards,
Cyril.
Hi Cyril,
thanks for your reply.
I generate several Classes and reference them via dynamical Type-Reference (similar to classes) in f.e. method-calls. When it comes to the step to reduce those custom Type-Reference i wan't to replace it with the Type (i think the ClassifierType would be best) of the previously generated class.
So i tried to use a Classifier-Type-<quotation> within an inline-template in the reduction-rules-section of my Generator's main with following steps:
1) i do a MAP_SRC-Node-Macro (followed by a COPY_SRC where i only copy the node returned by the surrounding MAP_SRC) where i can easily find the generated ClassConcept by its label and input-type (within the "mapped node"-section)
2) i create a ClassifierType-<quotation> which in turn complains correctly strict: <no classifier>
3) try to get my located ClassConcept into that quotation but without success :-( ... it cannot access the node grepped one line before from within the quotation... (with String or boolean it perfectly works)
So <quotation> does not work in the way i tried it...
Lastly i successfully did it with smodel language but it's not as far as pretty as it would be with <quotation> ;-). It is following (btw.: node is my dynamical Type-Reference):
node<ClassifierType> result = new node<ClassifierType>(<no prototypeNode>);
result.classifier = genContext.get output beanClass for (node.bean);
return result;
so my questions are:
1) how would i do it with <quotation>?
2) is the way i solve that problem somewhat elaborate (you know: do it within reduction-rule-section and the somewhat strange MAP_SRC+COPY_SRC-Combination)?
3) if i would do in the way described above, the smodel-statement or the <quotation> (if i get it run) would be executed every time my reduction rule comes into account... it would be obviously better to "cache" the one-time-generated ClassifierType (maybe also a mapping-label?). How/Where would you recommend me to do such things?
Thanks,
Mirko
Hi Mirko,
1) Think about a quotation as a "node literal", a construction similar to numeric constants and string literals. That is, you write a literal if you statically know what value do you mean. So inside a quotation you don't write an expression which evaluates to a node, you rather write the node itself. That is, an expression 2 + 3 evaluates to 5, an expression < 2 + 3 > (angled braces being quotation braces) evaluates to a node PlusExpression with leftOperand being IntegerConstant 3 and rightOperand being IntegerConstant 5.
So in your case where you know your exact Classifier only dynamically i.e. in runtime and not in design time you can't use just a quotation to create a ClassifierType which refers to this Classifier.
The good news, however, is that if you know the most part of a node statically and you want to replace only several parts of by dynamically-evaluated nodes you can use antiquotations. An antiquotation can be of 4 types: child, reference, property and list antiquotation. They both contain an expression which evaluates dynamically to replace a part of quoted node by its result. Child and referent antiquotations evaluate to a node, property antiquotation evaluates to string and list antiquotation evaluates to list of nodes.
So if you want to use quotation to create a ClassifierType with statically unknown Classifier you should do the following:
a) Create a quotation with a ClassifierType inside it. You did it already, and got <no classifier> inside your quotation.
b) Inside a cell for a reference to classifier, that is <no classifier> cell in your case, press "^" to create a reference antiquotation. An editor will look like this: < ^( .. )^ >
c) Inside an antiquotation, that is in between ^( )^ parntheses, write an expression which would evaluate to your Classifier, in your case it is " genContext.get output beanClass for (node.bean)"
d) Well done!
Other types of antiquotations look like %( )% for child, $( )$ for property and *( )* for child list. See MPS documentation on quotations for further info.
2) Another (and the best as I suppose) way to achieve you goal is to create a reduction rule applicable to your Type-Reference in template of which you should write a ClassifierType with a reference macro, inside of which macro you write your expression "genContext.get output beanClass for (node.bean)", may be casted to concept Classifier if necessary (i.e. if beanClass label does not specify its output concept).
Regards,
Cyril.
Hi Cyril,
thanks for that really good explanation!
It helped me a lot further, especially your description of antiquotation... with the example it is much better understandable than only out of the documentation ;-)
But, there is still one thing:
Your description worked very well, but wouldn't it be much better readable, if one could also see the concept-type of the quotation? I mean, in my case something like:
return <ClassifierType^( genContext.get output beanClass for (node.bean) )^>;
instead of
return <^( genContext.get output beanClass for (node.bean) )^>;
?
[for %( )%, $( )$ and *( )* respectively]
And:
There isn't much more information in the documentation at http://www.jetbrains.net/confluence/display/MPS/Typesystem#Typesystem-quotations ... is there another place where i can find documentation?
OK, and my second question i answered my self meanwhile: MAP_SRC + COPY_SRC doesn't make sense in my case as i may also reference "genContext.get output beanClass for (node.bean)" easily directly from within COPY_SRC too. ;-)
Anyway, thank you very much for your help!
Regards,
Mirko
Hi Mirko,
1)
You wrote:
"Your description worked very well, but wouldn't it be much better readable, if one could also see the concept-type of the quotation? I mean, in my case something like:
return <ClassifierType^( genContext.get output beanClass for (node.bean) )^>;
instead of
return <^( genContext.get output beanClass for (node.bean) )^>;
?"
One of the ideas behind the quotations is to use the same visual representation for quoted nodes as for the nodes in a program metalevel, so we are not going to alternate quoted node's editor in any way except replacing child's, referent's and property's cells with editors for antiquotations. However, your usability issue is well understandable and we'll do something to solve it. Would you mind to report it to our tracker?
2)
"There isn't much more information in the documentation at http://www.jetbrains.net/confluence/display/MPS/Typesystem#Typesystem-quotations ... is there another place where i can find documentation?"
Mea culpa. Actually, no more documentation on quotations exists. So, then it is me who will explain you. I've already told you about reference antiquotation, so child, list and property antiquotations are left to be explained.
a) If you want to replace a node somewhere inside a quoted node with a node evaluated by an expression, you use node antiquotation, that is %( )%. As you may guess there's no sense to replace the whole quoted node with an antiquotation with an expression inside, because you can write such an expression simply in your program instead.
So such an antiquotation is used to replace children, grandchildren, great-grandchildren and other descendants of a quoted node. Thus, an expression inside of antiquotation should return a node. To write such an antiquotation, position your caret on a cell for a child and type "%".
b) If you want to replace a child (or some more deeply located descendant) which is of a multiple-cardinality role, and if for that reason you may want to replace it not with a single node but rather with several ones, then use child list (simply list for brevity) antiquotations, *( )*. An expression inside a list antiquotation should return a list of nodes, that is of type nlist<..> or compatible type (i.e. list<node<..>> is ok, too, as well as some others). To write such an antiquotation, position your caret on a cell for a child inside a child collection and type "*". You can not use it on an empty child collection, so before you press "*" you have to enter a single child inside it.
с) If you want to replace a property value of a quoted node by a dynamicаlly calculated value, use property antiquotation $( )$. An expression inside a quotation should return string, which will be a value for an antiquoted property of a quoted node. To write such an antiquotation, position your caret on a cell for a property and type "$".
You are surely welcome to ask questions if you can't find an answer in MPS documentation. Such questions which may indicate lacks in our documentation, are always taken into consideration and will be reflected by updating our docs.
Regards,
Cyril.
Hi Cyril,
thanks for the information!
You wrote:
"Would you mind to report it to our tracker?"
already done. see http://youtrack.jetbrains.net/issue/MPS-6353
"You are surely welcome to ask questions if you can't find an answer in MPS documentation. Such questions which may indicate lacks in our documentation, are always taken into consideration and will be reflected by updating our docs."
Thank you, but don't forget to paste your (pretty good) explanations from this thread to the documentation ;-).
Regards,
Mirko