Collect all concrete types of children in typesystem rule

I've got a concept whose type should be the least common supertype of its children. I've already found the method leastCommonSupertypes in the SubtypingManager. The problem is that I can't collect a set of the concrete types of the children. Since these types are calculated after the nodes type I've to use when concrete blocks for each child. But of course my first shot failed:
final set<node<>> childTypes = new hashset<node<>>;
node.child.forEach({~c => 
  when concrete (typeof(c) as childType) { 
    childTypes.add(childType); 
  } 
});
typechecker.getSubtypingManager().leastCommonSupertypes(childTypes, true)
prettyPrint(); The argument set is always empty when the leastCommonSupertypes method is called.

Is the any way to delay the inference rule so that it is executed after the children's rules?
9 comments
All the "when_concrete" blocks are executed asynchronously and there is no guarantee on the order in which they are executed. However, each is going to be executed just once. So you could have a counter initialized to the number of children, which decreases with every "when_concrete" block, and you calculate the LCS when the counter hits zero.
0
Should I write something like
while (counter > 0) ;
prettyPrint(); before the method call? Are there any special sleep methods to decrease the CPU usage by this polling loop?
0
I meant you should write something like the following snippet:
int counter = node.child.size;
final set<node<>> childTypes = new hashset<node<>>;
node.child.forEach({~c => 
  when concrete (typeof(c) as childType) { 
    childTypes.add(childType);
    if (--counter == 0) {
      typeof(node) :==: typechecker.getSubtypingManager().leastCommonSupertypes(childTypes, true)
    }
  } 
});
prettyPrint();

Alternatively, you could assign fresh type variable to each of the children's types and make the resulting type a supertype of them all. Essentially you would instruct the typechecker to find the same LCS, only without the hassle.

node.child.forEach({~c => 
  typeof(node) :>=: typeof(c);
});
prettyPrint();
0
Your first suggestion should have come to my mind... Thanks for the clear explanation!

The second one looks interesting. I haven't already understand all details of the type inference rules. Will this version work if the children's types are not subtypes to each other? For example: There are the three types A, B, C with the type hierarchy
  A
/\
B  C
and the child nodes b of type B and c of type C. Will the resulting type be inferred to A?
0
Will the resulting type be inferred to A?


I don't see why not.
0
I've tested it and it works perfectly! I've made some wrong assumption regarding the :>=: operator. Can you recommend literature for the type inference mechanisms MPS uses?
I've also recognized that instead of when-concrete blocks I can use type variables. Are there any important advantages for one variant?
0
The algorithm typechecker is using is pretty much standard Hindley-Milner with subtyping added as an ad-hoc solution. We're actually not very happy with it and currently looking for an alternative.

As to "when concrete" vs. inequalities: if your typesystem is straightforward and type inference does not rely on the inner structure of types, you should avoid "when concretes". These are necessary when there's a need to inspect some type in order to construct another type. Such as inferring a type of a polymorphic method call from parameters.
0
Thank you very much for the information! Probably the HM theory is a very sophisticated introduction to the MPS typesystem.

I've just another type system related question in this context: How does MPS recognizes if two nodes type nodes matches each other? Is there any way to manipulate this behavior for a concept? In detail I want MPS to ignore the value of a property.
0
How does MPS recognizes if two nodes type nodes matches each other?


The comparison procedure matches each child and each property. For your task, you may want to explore node attributes as an alternative.
0

Please sign in to leave a comment.