From 6d8cadbdef36e7de2f82d36be83fe565b5ad1b20 Mon Sep 17 00:00:00 2001 From: Martin Jobst Date: Thu, 9 Jan 2025 12:58:52 +0100 Subject: [PATCH] Fix type inference for nested binary expressions 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. --- .../stcore/impl/ExpressionAnnotations.xtend | 4 +-- .../stcore/util/STCoreUtil.xtend | 6 +++- .../tests/TypeInferenceTest.java | 36 +++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/impl/ExpressionAnnotations.xtend b/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/impl/ExpressionAnnotations.xtend index 9be66cdf8c..b09886c126 100644 --- a/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/impl/ExpressionAnnotations.xtend +++ b/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/impl/ExpressionAnnotations.xtend @@ -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 diff --git a/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/util/STCoreUtil.xtend b/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/util/STCoreUtil.xtend index bd1463b8fa..de05a6aece 100644 --- a/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/util/STCoreUtil.xtend +++ b/plugins/org.eclipse.fordiac.ide.structuredtextcore.model/src/org/eclipse/fordiac/ide/structuredtextcore/stcore/util/STCoreUtil.xtend @@ -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 } @@ -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 diff --git a/plugins/org.eclipse.fordiac.ide.structuredtextfunctioneditor.tests/src/org/eclipse/fordiac/ide/structuredtextfunctioneditor/tests/TypeInferenceTest.java b/plugins/org.eclipse.fordiac.ide.structuredtextfunctioneditor.tests/src/org/eclipse/fordiac/ide/structuredtextfunctioneditor/tests/TypeInferenceTest.java index 8774308869..dc12c2af96 100644 --- a/plugins/org.eclipse.fordiac.ide.structuredtextfunctioneditor.tests/src/org/eclipse/fordiac/ide/structuredtextfunctioneditor/tests/TypeInferenceTest.java +++ b/plugins/org.eclipse.fordiac.ide.structuredtextfunctioneditor.tests/src/org/eclipse/fordiac/ide/structuredtextfunctioneditor/tests/TypeInferenceTest.java @@ -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; @@ -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(); }