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?

27 comments
Comment actions Permalink

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

0
Comment actions Permalink

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.

0
Comment actions Permalink

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.

0
Comment actions Permalink

It seems to me that your answer may be helpful. I'll try to use your advise.

0
Comment actions Permalink

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?

0
Comment actions Permalink

Hi Alex,

you should create a generator for your concepts which generates Java types from them.

Regards,

Cyril.

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

That works fine, thanks! The key was to define a 1-reference, not a 0..1 one.

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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.

0
Comment actions Permalink

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.

0
Comment actions Permalink

Works fine, thanks Igor

Best regards

jens

0
Comment actions Permalink

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

0
Comment actions Permalink

Hi Jens,

Thank you for the sample. I think it will be useful for me.

0
Comment actions Permalink

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.

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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.

0
Comment actions Permalink

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
0
Comment actions Permalink

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

0
Comment actions Permalink

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

0
Comment actions Permalink

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
0
Comment actions Permalink

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!

0
Comment actions Permalink

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.

0

Please sign in to leave a comment.