From f7aa9af04c027775c2a36167dba46b9713a108d5 Mon Sep 17 00:00:00 2001 From: Jonah Jeleniewski Date: Thu, 5 Dec 2024 12:01:19 +1100 Subject: [PATCH] Fix various intrinsic signatures around dynamic and open arrays --- CHANGELOG.md | 4 ++ .../delphi/type/factory/TypeFactoryImpl.java | 30 ++++++++++---- .../intrinsic/IntrinsicArgumentMatcher.java | 8 +--- .../type/intrinsic/IntrinsicReturnType.java | 31 ++------------ .../type/intrinsic/IntrinsicsInjector.java | 41 ++++++++++++++++--- .../IntrinsicArgumentMatcherTest.java | 10 ++--- 6 files changed, 73 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 179a822f5..0a6012ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Various intrinsic routines had incorrect signatures around dynamic and open arrays. + ## [1.12.0] - 2024-12-02 ### Added diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/factory/TypeFactoryImpl.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/factory/TypeFactoryImpl.java index 823848e2a..74f17b2b1 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/factory/TypeFactoryImpl.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/factory/TypeFactoryImpl.java @@ -84,6 +84,8 @@ public class TypeFactoryImpl implements TypeFactory { private final EnumMap intrinsicTypes; private final IntegerSubrangeType anonymousUInt15; private final IntegerSubrangeType anonymousUInt31; + private final IntegerType openArraySizeType; + private final IntegerType dynamicArraySizeType; private final PointerType nilPointer; private final FileType untypedFile; private final CollectionType emptySet; @@ -110,6 +112,18 @@ public TypeFactoryImpl(Toolchain toolchain, CompilerVersion compilerVersion) { ":AnonymousUInt31", BigInteger.ZERO, ((IntegerType) getIntrinsic(IntrinsicType.INTEGER)).max()); + + if (toolchain.architecture == Architecture.X86) { + this.openArraySizeType = (IntegerType) getIntrinsic(IntrinsicType.INTEGER); + this.dynamicArraySizeType = (IntegerType) getIntrinsic(IntrinsicType.INTEGER); + } else { + IntrinsicType openArraySizeIntrinsic = + compilerVersion.compareTo(VERSION_ATHENS) >= 0 + ? IntrinsicType.NATIVEINT + : IntrinsicType.INTEGER; + this.openArraySizeType = (IntegerType) getIntrinsic(openArraySizeIntrinsic); + this.dynamicArraySizeType = (IntegerType) getIntrinsic(IntrinsicType.NATIVEINT); + } } private boolean isReal48Bit() { @@ -556,6 +570,14 @@ public IntegerSubrangeType anonymousUInt31() { return anonymousUInt31; } + public IntegerType openArraySizeType() { + return openArraySizeType; + } + + public IntegerType dynamicArraySizeType() { + return dynamicArraySizeType; + } + @Override public IntegerType integerFromLiteralValue(BigInteger value) { return intrinsicTypes.values().stream() @@ -565,12 +587,4 @@ public IntegerType integerFromLiteralValue(BigInteger value) { .findFirst() .orElseThrow(IllegalStateException::new); } - - public CompilerVersion getCompilerVersion() { - return compilerVersion; - } - - public Toolchain getToolchain() { - return toolchain; - } } diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcher.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcher.java index f18a4970d..8a062572e 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcher.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcher.java @@ -27,12 +27,8 @@ public final class IntrinsicArgumentMatcher extends TypeImpl { public static final Type LIKE_DYNAMIC_ARRAY = new IntrinsicArgumentMatcher( - "", - type -> - type.isDynamicArray() - || type.isArrayConstructor() - || type.isString() - || type.isChar()); + "", + type -> type.isDynamicArray() || type.isArrayConstructor()); public static final Type ANY_STRING = new IntrinsicArgumentMatcher("", type -> type.isString() || type.isChar()); diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java index 84218bbff..b2b2959ab 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java @@ -26,8 +26,6 @@ import static org.sonar.plugins.communitydelphi.api.type.IntrinsicType.UNICODESTRING; import static org.sonar.plugins.communitydelphi.api.type.IntrinsicType.WIDECHAR; -import au.com.integradev.delphi.compiler.Architecture; -import au.com.integradev.delphi.compiler.CompilerVersion; import au.com.integradev.delphi.type.TypeImpl; import au.com.integradev.delphi.type.factory.ArrayOption; import au.com.integradev.delphi.type.factory.TypeFactoryImpl; @@ -42,8 +40,6 @@ import org.sonar.plugins.communitydelphi.api.type.TypeFactory; public abstract class IntrinsicReturnType extends TypeImpl { - private static final CompilerVersion VERSION_ATHENS = CompilerVersion.fromVersionNumber("36.0"); - @Override public String getImage() { return "<" + getClass().getSimpleName() + ">"; @@ -97,25 +93,6 @@ public static Type argumentByIndex(int index) { return new ArgumentByIndexReturnType(index); } - private static Type getOpenArraySizeType(TypeFactory typeFactory) { - if (((TypeFactoryImpl) typeFactory).getToolchain().architecture == Architecture.X86) { - return typeFactory.getIntrinsic(IntrinsicType.INTEGER); - } else { - return typeFactory.getIntrinsic( - ((TypeFactoryImpl) typeFactory).getCompilerVersion().compareTo(VERSION_ATHENS) >= 0 - ? IntrinsicType.NATIVEINT - : IntrinsicType.INTEGER); - } - } - - private static Type getDynamicArraySizeType(TypeFactory typeFactory) { - if (((TypeFactoryImpl) typeFactory).getToolchain().architecture == Architecture.X86) { - return typeFactory.getIntrinsic(IntrinsicType.INTEGER); - } else { - return typeFactory.getIntrinsic(IntrinsicType.NATIVEINT); - } - } - private static final class LengthReturnType extends IntrinsicReturnType { private final Type byteType; private final Type integerType; @@ -126,8 +103,8 @@ private static final class LengthReturnType extends IntrinsicReturnType { private LengthReturnType(TypeFactory typeFactory) { this.byteType = typeFactory.getIntrinsic(IntrinsicType.BYTE); this.integerType = typeFactory.getIntrinsic(IntrinsicType.INTEGER); - this.openArraySizeType = getOpenArraySizeType(typeFactory); - this.dynamicArraySizeType = getDynamicArraySizeType(typeFactory); + this.openArraySizeType = ((TypeFactoryImpl) typeFactory).openArraySizeType(); + this.dynamicArraySizeType = ((TypeFactoryImpl) typeFactory).dynamicArraySizeType(); } @Override @@ -152,8 +129,8 @@ private static final class HighLowReturnType extends IntrinsicReturnType { private HighLowReturnType(TypeFactory typeFactory) { this.integerType = typeFactory.getIntrinsic(IntrinsicType.INTEGER); - this.openArraySizeType = getOpenArraySizeType(typeFactory); - this.dynamicArraySizeType = getDynamicArraySizeType(typeFactory); + this.openArraySizeType = ((TypeFactoryImpl) typeFactory).openArraySizeType(); + this.dynamicArraySizeType = ((TypeFactoryImpl) typeFactory).dynamicArraySizeType(); } @Override diff --git a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java index 92ed9affe..414235dcc 100644 --- a/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java +++ b/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicsInjector.java @@ -54,6 +54,7 @@ import au.com.integradev.delphi.symbol.declaration.TypeNameDeclarationImpl; import au.com.integradev.delphi.symbol.declaration.VariableNameDeclarationImpl; import au.com.integradev.delphi.symbol.scope.DelphiScopeImpl; +import au.com.integradev.delphi.type.factory.TypeFactoryImpl; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -87,6 +88,14 @@ private Type type(IntrinsicType type) { return typeFactory.getIntrinsic(type); } + private Type openArraySizeType() { + return ((TypeFactoryImpl) typeFactory).openArraySizeType(); + } + + private Type dynamicArraySizeType() { + return ((TypeFactoryImpl) typeFactory).dynamicArraySizeType(); + } + private void buildRoutines() { routine("Abs").param(type(REAL)).returns(type(REAL)); routine("Abs").param(type(INTEGER)).returns(type(INTEGER)); @@ -162,6 +171,11 @@ private void buildRoutines() { .param(LIKE_DYNAMIC_ARRAY) .variadic(LIKE_DYNAMIC_ARRAY) .returns(IntrinsicReturnType.concat(typeFactory)); + routine("Concat") + .param(ANY_STRING) + .param(ANY_STRING) + .variadic(ANY_STRING) + .returns(IntrinsicReturnType.concat(typeFactory)); routine("Continue"); routine("Copy") .param(type(PANSICHAR)) @@ -174,9 +188,14 @@ private void buildRoutines() { .param(type(INTEGER)) .returns(IntrinsicReturnType.copy(typeFactory)); routine("Copy") - .param(LIKE_DYNAMIC_ARRAY) + .param(ANY_STRING) .param(type(INTEGER)) .param(type(INTEGER)) + .returns(IntrinsicReturnType.copy(typeFactory)); + routine("Copy") + .param(LIKE_DYNAMIC_ARRAY) + .param(dynamicArraySizeType()) + .param(dynamicArraySizeType()) .required(1) .returns(IntrinsicReturnType.copy(typeFactory)); routine("Dec").varParam(ANY_ORDINAL).param(type(INTEGER)).required(1); @@ -184,7 +203,11 @@ private void buildRoutines() { routine("Default") .param(ANY_CLASS_REFERENCE) .returns(IntrinsicReturnType.classReferenceValue()); - routine("Delete").varParam(LIKE_DYNAMIC_ARRAY).param(type(INTEGER)).param(type(INTEGER)); + routine("Delete").varParam(ANY_STRING).param(type(INTEGER)).param(type(INTEGER)); + routine("Delete") + .varParam(LIKE_DYNAMIC_ARRAY) + .param(dynamicArraySizeType()) + .param(dynamicArraySizeType()); routine("Dispose").varParam(ANY_POINTER); routine("Eof").varParam(ANY_FILE).required(0).returns(type(BOOLEAN)); routine("Eoln").varParam(ANY_FILE).required(0).returns(type(BOOLEAN)); @@ -209,7 +232,11 @@ private void buildRoutines() { routine("Inc").varParam(ANY_TYPED_POINTER).param(type(INTEGER)).required(1); routine("Include").varParam(ANY_SET).param(ANY_ORDINAL); routine("Initialize").varParam(TypeFactory.untypedType()).param(type(NATIVEINT)).required(1); - routine("Insert").param(LIKE_DYNAMIC_ARRAY).varParam(LIKE_DYNAMIC_ARRAY).param(type(INTEGER)); + routine("Insert").param(ANY_STRING).varParam(ANY_STRING).param(type(INTEGER)); + routine("Insert") + .param(LIKE_DYNAMIC_ARRAY) + .varParam(LIKE_DYNAMIC_ARRAY) + .param(dynamicArraySizeType()); routine("IsConstValue").param(TypeFactory.untypedType()).returns(type(BOOLEAN)); routine("IsManagedType").param(ANY_CLASS_REFERENCE).returns(type(BOOLEAN)); routine("Length").param(type(SHORTSTRING)).returns(IntrinsicReturnType.length(typeFactory)); @@ -251,7 +278,11 @@ private void buildRoutines() { routine("Seek").varParam(ANY_FILE).param(type(INTEGER)); routine("SeekEof").varParam(ANY_TEXT_FILE).required(0).returns(type(BOOLEAN)); routine("SeekEoln").varParam(ANY_TEXT_FILE).required(0).returns(type(BOOLEAN)); - routine("SetLength").varParam(LIKE_DYNAMIC_ARRAY).param(type(INTEGER)).variadic(type(INTEGER)); + routine("SetLength").varParam(ANY_STRING).param(type(INTEGER)); + routine("SetLength") + .varParam(LIKE_DYNAMIC_ARRAY) + .param(dynamicArraySizeType()) + .variadic(dynamicArraySizeType()); routine("SetString").varParam(ANY_STRING).param(type(PANSICHAR)).param(type(INTEGER)); routine("SetString").varParam(ANY_STRING).param(type(PWIDECHAR)).param(type(INTEGER)); routine("SetTextBuf") @@ -262,7 +293,7 @@ private void buildRoutines() { routine("SizeOf").param(TypeFactory.untypedType()).returns(type(INTEGER)); routine("Slice") .varParam(ANY_ARRAY) - .param(type(INTEGER)) + .param(openArraySizeType()) .returns(IntrinsicReturnType.slice(typeFactory)); routine("Sqr").param(type(EXTENDED)).returns(type(EXTENDED)); routine("Sqr").param(type(INTEGER)).returns(type(INTEGER)); diff --git a/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcherTest.java b/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcherTest.java index ecd760437..f5d90709d 100644 --- a/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcherTest.java +++ b/delphi-frontend/src/test/java/au/com/integradev/delphi/type/intrinsic/IntrinsicArgumentMatcherTest.java @@ -63,14 +63,14 @@ void testLikeDynamicArray() { assertThat(matches(LIKE_DYNAMIC_ARRAY, dynamicArray)).isTrue(); assertThat(matches(LIKE_DYNAMIC_ARRAY, arrayConstructor)).isTrue(); - assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.ANSICHAR))).isTrue(); - assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.WIDECHAR))).isTrue(); + assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.ANSICHAR))).isFalse(); + assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.WIDECHAR))).isFalse(); assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.SHORTSTRING))) - .isTrue(); + .isFalse(); assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.ANSISTRING))) - .isTrue(); + .isFalse(); assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.getIntrinsic(IntrinsicType.UNICODESTRING))) - .isTrue(); + .isFalse(); assertThat(matches(LIKE_DYNAMIC_ARRAY, fixedArray)).isFalse(); assertThat(matches(LIKE_DYNAMIC_ARRAY, FACTORY.emptySet())).isFalse(); }