How to create type system
MPS is very interesting product, with greate future, but the documentation is poor. I tried to create simple language for describing entities. The syntax is simple:
entity SomeEntity
property id : Long
property name : String
property anotherEntity : AnotherEntity
I created two concepts: 'Entity' and 'Property' with property 'type'. The 'type' can be some Java type or reference to another entity. How to check the value of the property 'type'? I read the documentation but I didn't understand how to create the type system is this case. Perhaps, I should use a separate concept for a type, not a property of concept?
Please sign in to leave a comment.
You might use BaseLanguage's types for your declarations (not good idea, but possible) or you could create your own domain-specific types (gives you absolute control).
It might be 'Enum data type' (MPS built-in concept, like string or integer), or you can create your own concepts hierarhy.
If you use Enum, create properties of your concepts of that type.
If you use Concept (either your own or BaseLanguage's), declare it as 0..1 (for optional properties, for example) child.
In case you wish to use BL types, just add reference to jetbrains.mps.baseLanguage and look at it's jetbrains.mps.baseLanguage.structure.Type and it's hierarchy
Hi Alex,
You wrote: "I created two concepts: 'Entity' and 'Property' with property 'type'. The 'type' can be some Java type or reference to another entity."
It sounds strange because properties of an MPS node are atomic values: they are simply strings (or ints or booleans). So you can not store Java types or references in properties, or may be you meant something different by word "property".
To solve your problem I'd rather create such an hierarchy:
PropertyType (abstract concept)
JavaType extends PropertyType, contains a child of a concept jetbrains.mps.baseLanguage.Type
EntityType extends PropertyType, contains a reference to Entity
Your concept named Property would contain a child of a concept PropertyType.
By the way, to understand typesystem better you should remember that a type is always a node (not string not property etc.). It is even written in documentation on typesystem.
Regards,
Cyril.
Hi Alexander, you can not use Enum property value as MPS typesystem type, because a type is always a node, meanwhile Enum property is a string value property with only several allowed string values, exactly those which are declared in Enum property type delcaration.
Regards,
Cyril.
It seems to me that your answer may be helpful. I'll try to use your advise.
I tried your advise. I created the hierarchy of concepts and generator. There is an abstract concept 'PropertyType' and its inheritors: 'EntityType' with reference to 'Entity' and 'JavaType' with child node 'Type'.
The entity declaration was:
entity Device
property test : Device
property test1 : string
The generated text was:
public class Device {
private <!TextGen not found for 'entity.structure.EntityType'!> test;
private <!TextGen not found for 'entity.structure.JavaType'!> test1;
}
What does it mean? As I understand, I must to add something to my concepts... What?
Hi Alex,
you should create a generator for your concepts which generates Java types from them.
Regards,
Cyril.
How do I have to set up the editor for EntityType? If I create concepts as
you do I'm able to create entities with properties of java types, but can't reference ones of entity types.
My EntityType editor is a simple (%entityType%->{name}) so it should be able to enter the name of the referenced entity.
If I create a solution and try to use a property of EntityType, the EntityType appears in the popup list (as the JavaType does).
I choose the EntityType but can't enter the "Device" name. A JavaType property with e.g. string works fine.
Best regards,
jens
You made mistake in editor. The editor must be (%entity%->{name}), not entityType. EntityType concept must have reference to Entity concept with cardinality 1. Add it to section ''references".
Best regards,
Alex S
That works fine, thanks! The key was to define a 1-reference, not a 0..1 one.
Hi Cyril,
speaking of creating a generator - I've played a bit with this typesystem and craeted a generator with gtext to generate a simple text output.
Now I want to write out the choosen type of the solution - e.g. Device for the entity or string for the JavaType.
In the generator I have already a PropertyMacro for the name (node.name) - works fine.
For the type I have to distinguish in the PropertyMacro between EntityType and JavaType to get the type. Can be done with node.type.instanceOf and ?: operator,
but how can I cast the PropertyType to the EntityType to follow the reference and get the name of the entity?
And is there a better way than ?: in case of having more Type concepts?
Best regards
jens
One more thing to mention: I thought the "Behavior" is what I'm looking for: there I can create a method which returns the right value by some sort of polymorphism mechanism. But in baseLanguage there are "virtual" and "override" keywords I think I have to use too but my behavior editor does not accept them. Do I have to change a configuration somewhere or add another used language?
Best regards,
jens
Hi Jens,
To make a method virtual use intentions: Alt-Enter to get intentions menu.
To make a method overriding other method select name of method you want to override in completion menu of your method's name.
Igor.
I created textGens for JavaType and EntityType.
In JavaType_TextGen I wrote append ${node.type}. It works. In EntityType_TextGen I wote append ${node.entity.name}. It does not work. When I trying to generate text I receive following errors:
couldn't resolve reference 'entity' in output node [type] EntityType <no name>[8613613947967781656] in entitytest.sandbox.sandbox@1_1
-- input node was [propertyType] EntityType <no name>[1516979138000269500] in entitytest.sandbox.sandbox@1_0
bad reference 'entity' in input node [type] EntityType <no name>[8613613947967781656] in entitytest.sandbox.sandbox@1_1
Maybe it incorrect to write append ${node.entity.name} ? There is no any word about textGen in MPS documentation.
Works fine, thanks Igor
Best regards
jens
Hi alex,
as you noticed I've had also played with your typesystem sample. Finally it works, I've published the project with
http://github.com/mpSamples/mps.typesystem
Have fun.
Best regards
jens
Hi Jens,
Thank you for the sample. I think it will be useful for me.
Hi, Jens
Your sample works fine, but has one difference. You used gtext for generating output. But I tried to use baseLanguage. I created the following construction for property declaration:
private $COPY_SRC$[?] $[propertyName]
In your sample you created behavior method getTypeName() and used it in propertyMacro. It works with gtext perfectly. But it is impossible to use propertyMacro for type with baseLanguage. COPY_SRC macro works fine for JavaType, but can't resolve reference to entity for EntityType because the reference is null.
Hi alex,
I did use gtext because of a discussion in this forum some weeks ago. I asked which method would be best to generate text files.
What do you try? Generate Java code?
Anyway, never thought that it makes a difference which generator you use when using a behavior method because that's part of
the language and should be equal in any cases.
Best regards,
jens
Well, yaeh, instantly I see the difference with generators: in gtext the property macro has to evaluate to a string (which does the behaviour), in baseLanguage it has to evaluate to a node!
Since baseLanguage represents Java, I guess EntityType has to create a node<> of Java class type or so. The trick is that the entity may reference itself, so infinite loops may occur.
Any hints from JetBrains folks?
Best regards
jens
Well, I thought something like that should work: genContext.outputModel.roots(Entity).findFirst({~it => it.name == node.propertyType.getTypeName(); })
take the output model, find all roots of Entity and take the first with the name I got from behaviour. Since I used a property macro to name the generated class
one item could be found. But does not work - maybe the outputModel is not what I think it is or it is not ready for use or it.name is not what I think it is or...
Well, a debugger would be cool to set a breakpoint on use of the node macro to explore the data.
Best regards,
jens
I agree with you about debugger. It would be a useful feature.
I experimented with the sample last three days and got an acceptable result. I'll prepare a short description and post it in the nearest time.
I promised to publish my version of the typesystem for entities. You can see it in the attached file. I created three concepts: Entity, EntityType (extends Type) and Property. EntityType contains property 'name'.
The editor for EntityType is:
[> entityref {name} <]
Also I added a menu for the cell {name}:
property values
values : (scope, operationContext, node)->list<string> {
nlist<Entity> entities = node.model.roots(Entity);
list<string> names = new arraylist<string>;
foreach entity in entities {
names.add(entity.name);
}
names;
}
Now when I press Ctrl+Enter I see EntityType with other types (string, long, etc.) in the popup. I choose it. The 'entityref <no name>' appears. I press Ctrl+Enter in the 'name' cell and choose entity name from popup. There is only one problem. The word entityref is unnecessary. But I could't create this construction without it because the popup with types overlaps the popup with entity names.
Attachment(s):
entitytest.zip
I tried your advise but it did't work. The problem described here http://www.jetbrains.net/devnet/message/5250084#5250084
I have chosen another way but I'm not sure is it correct.
I posted my solution here http://www.jetbrains.net/devnet/message/5250489#5250489
Hi alex,
I'm interested how your solution looks like, in the next slack time I'll have a look at it!
Best regards
jens
Hi Alex,
I found some time to play again with the typesystem (my version from github). I've added a Java generator. It works with the same principle as yours.
But I don't extend Type in EntityType, I extend PropertyType as we did in the first version. The generator uses a DummyType which extends Type
to present a fitting node.
Because I cant post the diffs with my current computer to github, I've attachted the project here.
Best regards
jens
Attachment(s):
mps.samples.typesystem.rar.zip
Hi Alex,
> There is only one problem. The word entityref is unnecessary.
So you could do a little trick: put the cursor on the entityref cell, open the inspector, delete the "entityref" text in text field in section Constant cell, and add two styles:
<no base style> {
punctuation-left : true
punctuation-right : true
}
This makes it nearly unvisible.
Best regards
jens
P.S. Your menu is really cool stuff!
Hi, Jens
Sorry for delayed replay. Thanks for the answer. I found that your solution is simple and it works perfectly.
However, I thought that the baseLanguage can contains a solution. It has the same construction: the ClassifierType is referenced to the Classifier. But the code is very complicated. Unfortunatelly I don't understand it yet.