[SOLVED] Own binary relationship always yields : "Argument of WHEN CONCRETE block is never concrete"

Hi all,

similar to [1] I have the "WHEN CONCRETE block is never concrete" warning:

However, unlike the issue with the calculator example I created my own binary operation which copies all elements from a PlusExpression (find the language in [2]). Nevertheless I seem to be unable to get rid of this warning. Users are very confused by this message and therefore I would really love to get rid of it. 

All my tries with the typesystem did not work and the error persists. I eventually extended the calculator example with a binary operation (MyPlusExpression):

Here the typesystem tells me I cannot apply this operator to int-int (due to the typeof_InputFieldReference rule) - however if my MyPlusExpressin extends the PlusExpression everything is fine?

 

What am I doing wrong here? Surely there is some further checks I am unable to find? Do I have to give my binary operation a special typesystem rule to work correctly?

Any help appreciated! Thanks!

 

[1] https://mps-support.jetbrains.com/hc/en-us/community/posts/207221229-warning-argument-of-When-Concrete-block-is-never-concrete?input_string=%22WHEN%20CONCRETE%20block%20is%20never%20concrete

 [2] https://github.com/nkoester/TrafoMenuTest

2 comments
Comment actions Permalink

Hi,

since you extend BinaryOperation, which in "typeof_BinaryOperation" invokes "operation type(operation, leftType, rightType)" to calculate the resulting type of applying your operator to two values. When you "extend" a PlusExpression, you inherit its "overloaded operations rules" defined in "BL_PlusExpression". When you do not extend PlusExpression, there is no way to calculate the type of the operation from the types of its left and right expressions, thus the error "cannot apply to int-int". You can read more on this in the "Overloaded Operators" section of https://confluence.jetbrains.com/display/MPSD34/Typesystem.

You have two possibilities to resolve the issue, depending on how you want to use your binary expression. If you need the flexibility to compare different types and calculate the resulting type of your binary operation from the types of the left and right children, create a an "overloaded operations rules". This simple one fixed your project for me:

overloaded operations rules My 

operation concepts: MyBinaryRel
left operand type: new node<IntegerType>() is exact: false use strong subtyping false
right operand type: new node<IntegerType>() is exact: false use strong subtyping false
is applicable:
<no isApplicable>
operation type:
(operation, leftOperandType, rightOperandType)->node<> {
if (leftOperandType.isInstanceOf(NullType) || rightOperandType.isInstanceOf(NullType)) {
return null;
} else {
return new node<IntegerType>();
}
}
-----------------------------------------------

If, on the other hand, You'll always be comparing integers and the derived type of the binary operation should also always be integer, just define an inference rule like this:

inference rule typeof_MyBinaryRel { 
applicable for concept = MyBinaryRel as myBinaryRel
applicable always
overrides {
true;
}

do {
infer typeof(myBinaryRel.leftExpression) :<=: new node<IntegerType>();
infer typeof(myBinaryRel.rightExpression) :<=: new node<IntegerType>();
typeof(myBinaryRel) :==: new node<IntegerType>();
}
}

Be sure you set the "overrides" flag to "true" in order to suppress/override the "typeof_BinaryOperation" rule of BinaryOperation.

Cheers,

Vaclav

1
Comment actions Permalink

Yes! Thank you very much for this detailed answer Vaclav! I managed to use your tips and added it to the project if anyone else faces this issue.

0

Please sign in to leave a comment.