How does the combination Inference Rule and Overloaded Operations Rules work?
Hi community,
I'm currently working on an expression language. For this purpose I utilized the existing expression language from https://github.com/gsdlab/claferMPS/tree/master/code/languages/org.clafer.mps (thx to Markus Voelter). It works pretty fine with one exception: It seems that the overloaded operations rules are not evaluated.
Scenario:
Let's say there is a concept called "BinaryExpression" that has two children of concept "Expression" called "left" and "right". If I write an equation like...
But "operation type(...)" always evaluates to null (no matter if it is a multiplication, division, subtraction or addition, etc.).
The overloaded operation rules look as follows:
Has anybody an idea why this happens?
Thank you very much in advance!
LaAck
I'm currently working on an expression language. For this purpose I utilized the existing expression language from https://github.com/gsdlab/claferMPS/tree/master/code/languages/org.clafer.mps (thx to Markus Voelter). It works pretty fine with one exception: It seems that the overloaded operations rules are not evaluated.
Scenario:
Let's say there is a concept called "BinaryExpression" that has two children of concept "Expression" called "left" and "right". If I write an equation like...
3.0 * 7.0... I get an type system error with "operator * cannot be applied to double and double". This error occurs if the types of the operands can be calculated but the type of the operation is null. The operation's type is calculated in the following type inference rule:
rule typeof_BinaryExpression {
applicable for concept = BinaryExpression as be
overrides false
do {
when concrete (typeof(be.left) as leftType) {
when concrete (typeof(be.right) as rightType) {
node<> optype = operation type(be, leftType, rightType);
info "optype is " + optype;
if (optype != null) {
typeof(be) :==: optype;
} else {
if (leftType == null) {
error "left side was not set" -> be;
}
if (rightType == null) {
error "right side was not set" -> be;
}
if (leftType != null && rightType != null) {
error "operator " + be.concept.conceptAlias + " cannot be applied to " + leftType/.getPresentation() + " and " + rightType/.getPresentation() -> be;
}
}
}
}
}
}
But "operation type(...)" always evaluates to null (no matter if it is a multiplication, division, subtraction or addition, etc.).
The overloaded operation rules look as follows:
operation concepts: BinaryArithmeticExpression
left operand type: new node<PrimitiveType>() is exact: false use strong subtyping false
right operand type: new node<PrimitiveType>() is exact: false use strong subtyping false
is applicable:
<no isApplicable>
operation type:
(operation, leftOperandType, rightOperandType)->node<> {
if (operation.isStaticallyEvaluatable()) { return NumberEvaluationHelper.staticType(leftOperandType, rightOperandType, operation); }
// Check if both operants have the same type
if (leftOperandType.concept.isExactly(# rightOperandType.concept)) { return leftOperandType; }
node<> commenSuperType = AssignableSuperTypeHelper.getCommonSuperType(leftOperandType, rightOperandType);
return commenSuperType;
}
Has anybody an idea why this happens?
Thank you very much in advance!
LaAck
Please sign in to leave a comment.
This should help narrow down the cause of the trouble.
Vaclav
thank you very much for your reply. I'm very sorry, I forget to put this piece of information in my issue description. I already checked whether the overloaded operation rules are called or not. Actually they are NOT called. So I checked whether the operation concept and the operand types fit. During runtime the following arguments given to the function "operation type(be,leftType,rightType)":
To my current understanding the overloaded operation rule should be called. Do you have any ideas why it is not?
Thank you again in advance,
LaAck
here's one thing that you need to be careful about here - the overloaded operations rules matches to a type or its super-type, not its super-concept!
It seems to me that you are mixing two hierarchies - the hierarchy of concepts and the hierarchy of types. Instead of matching against "new node<PrimitiveType>()" you should be checking against a type, that is declared as a super-type of your DoubleType in some sub-typing rule.
I hope this helps shed some light into the issue.
Cheers,
Vaclav
awesome, this solved the issue! Thank you very much. In my defense I have to say, that I just re-used the expression language I mentioned in my first post about this issue. ;) Anyway. The final solution was to introduce another sub-typing rule which declares DoubleType to be a sub-type of PrimitiveType. I thought that, as long the concept DoubleType inherits from PrimitiveType, the type system rules are also inherited (if they are not overridden by a sub-concepts type inference rule). According to your explanations I think this was my error in reasoning.
So thank you very much again!
Best regards,
LaAck