Skip to content

Commit

Permalink
Fix type inference for nested binary expressions
Browse files Browse the repository at this point in the history
There was a problem where operand types were not converted to the
required unsigned or bit types before determining the common result
type. Also fix equivalent unsigned type for INT.
  • Loading branch information
mx990 authored and azoitl committed Jan 9, 2025
1 parent a6cfce7 commit 6d8cadb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ final package class ExpressionAnnotations {
else if (left instanceof AnyDurationType && right instanceof AnyDurationType)
left.commonSupertype(right)
else
left.commonSupertype(right).equivalentAnyNumType
commonSupertype(left.equivalentAnyNumType, right.equivalentAnyNumType)
} else if (expr.op.logical) {
left.commonSupertype(right).equivalentAnyBitType
commonSupertype(left.equivalentAnyBitType, right.equivalentAnyBitType)
} else if (expr.op.range) {
left.commonSupertype(right)
} else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,10 @@ final class STCoreUtil {
(type.isAssignableFrom(other.equivalentAnyUnsignedType) ||
other.equivalentAnyUnsignedType.isAssignableFrom(type)))
type
else if (type instanceof AnyBitType &&
(type.isAssignableFrom(other.equivalentAnyBitType) ||
other.equivalentAnyBitType.isAssignableFrom(type)))
type
else // fallback to other _only_ if type is not compatible
other
}
Expand All @@ -602,7 +606,7 @@ final class STCoreUtil {
def static AnyUnsignedType getEquivalentAnyUnsignedType(INamedElement type) {
switch (type) {
SintType: ElementaryTypes.USINT
IntType: ElementaryTypes.ULINT
IntType: ElementaryTypes.UINT
DintType: ElementaryTypes.UDINT
LintType: ElementaryTypes.ULINT
AnyUnsignedType: type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
import org.eclipse.xtext.testing.util.ParseHelper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
Expand Down Expand Up @@ -305,6 +306,41 @@ void testStandardFunctionCallWithBinaryExpression(final String typeName, final S
"left declared result type");
}

@Test
void testNestedBinaryExpression() throws Exception {
final var result = parseHelper.parse("""
FUNCTION test
VAR_TEMP
X : BOOL;
Y : DWORD;
END_VAR
X := X AND ((Y AND 16#0000_1000) <> 0);
END_IF;
END_FUNCTION
""");
final STAssignment assignment = (STAssignment) getFirstStatement(result);
final STBinaryExpression outer = (STBinaryExpression) assignment.getRight();
assertEquals(ElementaryTypes.BOOL, outer.getResultType(), "outer result type");
assertEquals(ElementaryTypes.BOOL, outer.getDeclaredResultType(), "outer declared result type");

final STBinaryExpression inner = (STBinaryExpression) outer.getRight();
assertEquals(ElementaryTypes.BOOL, inner.getResultType(), "inner result type");
assertEquals(ElementaryTypes.BOOL, inner.getDeclaredResultType(), "inner declared result type");

final STExpression innerRight = inner.getRight();
assertEquals(ElementaryTypes.DWORD, innerRight.getResultType(), "inner right result type");
assertEquals(ElementaryTypes.SINT, innerRight.getDeclaredResultType(), "inner right declared result type");

final STBinaryExpression innermost = (STBinaryExpression) inner.getLeft();
assertEquals(ElementaryTypes.DWORD, innermost.getResultType(), "innermost result type");
assertEquals(ElementaryTypes.DWORD, innermost.getDeclaredResultType(), "innermost declared result type");

final STExpression innermostRight = innermost.getRight();
assertEquals(ElementaryTypes.WORD, innermostRight.getResultType(), "innermost right result type");
assertEquals(ElementaryTypes.INT, innermostRight.getDeclaredResultType(),
"innermost right declared result type");
}

private static STStatement getFirstStatement(final STFunctionSource source) {
return source.getFunctions().getFirst().getCode().getFirst();
}
Expand Down

0 comments on commit 6d8cadb

Please sign in to comment.